Home > Software design >  Class inside Class and function. AttributeError: 'My_Data' object has no attribute 'O
Class inside Class and function. AttributeError: 'My_Data' object has no attribute 'O

Time:01-26

This code throws me an error due to the class. I get the error:

AttributeError: 'My_Data' object has no attribute 'Other'

The error is in the row My_Dictionary[row[0]].Other.append(row[3])

The problem certainly concerns the classes, because this code works correctly if: i use it without the Page1 class, but using only the My_Data class (without self in init). I've reduced and simplified the code as much as possible, removing useless but obvious parts for solving the question. Thank you

How can I fix? Thank you

    class Page1(tk.Frame):
        def __init__(self, master, other, **kw):
            super().__init__(master, **kw)
            self.configure(bg='white')
    
            class My_Data():
                def __init__(self, Name, Year, Other):
                    self.Name: str
                    self.Year: float
                    self.Other: list[int]
                    
            def function1(self):
                My_Dictionary = {}
                x = cursor.execute("sql")
    
                for row in x.fetchall():
                    if row[0] not in My_Dictionary:
                        Data = My_Data(
                            Name=row[1],
                            Year=row[2],
                            Other=list())
    
                        My_Dictionary[row[0]] = info
                    My_Dictionary[row[0]].Other.append(row[3])
                print(My_Dictionary)

UPDATE My previous code that worked fine, if: i use it without the Page1 class, but using only the My_Data class (without self in init):

class My_Data:
    Name: str
    Year: float
    Other: list[int]


def function1():
    My_Dictionary = {}
    x = cursor_test.execute("sql")

    for row in x.fetchall():
        if row[0] not in My_Dictionary:
            
            info = My_Data(
                        Name=row[1],
                        Year=row[2],
                        Other=list())

            My_Dictionary[row[0]] = info
        My_Dictionary[row[0]].Other.append(row[3])

CodePudding user response:

  • Don't use nested classes unless you really need to and know how.
  • self.Name: str is an annotation that does nothing; your constructor is not setting any of the fields, hence "no attribute". You would do self.Name: str = Name to assign them, but...
  • ... it's easier to use a dataclass, that figures out the constructor for you.
  • Then, Data and info are not the same. Your IDE should highlight one as unused, which should already be a clue that you're not doing something right.

All in all:

import dataclasses


@dataclasses.dataclass
class My_Data:
    Name = str
    Year = float
    Other: list


class Page1(tk.Frame):
    def __init__(self, master, other, **kw):
        super().__init__(master, **kw)
        self.configure(bg="white")

    def function1(self):
        My_Dictionary = {}
        x = cursor.execute("sql")

        for row in x.fetchall():
            if row[0] not in My_Dictionary:
                info = My_Data(
                    Name=row[1],
                    Year=row[2],
                    Other=list(),
                )
                My_Dictionary[row[0]] = info
            My_Dictionary[row[0]].Other.append(row[3])
        print(My_Dictionary)

CodePudding user response:

The specific problem you're asking about is caused by the fact that your MyData class's __init__ method doesn't actually do anything.

class My_Data():
    def __init__(self, Name, Year, Other):
        self.Name: str
        self.Year: float
        self.Other: list[int]

These statements are type hints and do not actually assign any attributes to the instance of your class. You can keep them as type hints are useful, but they should be defined outside any method and without self. And if you're using type hints, might as well put 'em on the arguments to __init__ too.

So you want something like this:

class My_Data():

    Name: str
    Year: int
    Other: list[int]

    def __init__(self, Name: str, Year: int, Other: list[int]):
        self.Name = Name
        self.Year = Year
        self.Other = Other

(Note I changed Year to an integer.)

CodePudding user response:

The error you're seeing is a AttributeError, which means that the object you're trying to access a property or method on doesn't have that attribute. In this case, the error message is saying that the My_Data object has no attribute Other.

The problem seems to be that you are trying to access; My_Dictionary[row[0]].Other.append(row[3]) but Other is not a proper of the My_Data class.

It seems that you have defined 'Other' attribute in the constructor of class 'My_Data' but in the function1, you are trying to access it as a property of the object instead of a attribute of the class.

class Page1(tk.Frame):
def __init__(self, master, other, **kw):
    super().__init__(master, **kw)
    self.configure(bg='white')

    class My_Data():
        def __init__(self, Name, Year):
            self.Name: Name
            self.Year: Year
            self.Other = []
            
    def function1(self):
        My_Dictionary = {}
        x = cursor.execute("sql")

        for row in x.fetchall():
            if row[0] not in My_Dictionary:
                Data = My_Data(
                    Name=row[1],
                    Year=row[2])

                My_Dictionary[row[0]] = Data
            My_Dictionary[row[0]].Other.append(row[3])
         print(My_Dictionary)
  • Related