Home > Mobile >  Confuse about self attribute and declaration in Python
Confuse about self attribute and declaration in Python

Time:10-27

i am currently trying to understand some basic concept of Python.

Here is my code :

class BorgSingleton:
    _shared_borg_state = {}
    test = "toto"

    def __init__(self):
        self.__dict__ = self._shared_borg_state
        print("borg created")
        print(self.test)
    
class Point(BorgSingleton) :

    def __init__(self, lat, long):
        self.latitude = lat
        self.longitude = long
        super().__init__()
        print (self.latitude)
    
    def g(self) :
        return BorgSingleton.test  " "  str(self.latitude)   " "   str(self.longitude)
    
    
def main():
    point_1 = Point(5,2)
    point_2 = Point(3,3)
    print(point_1.g())
    print(point_2.g())
    point_1.test = "tata"
    print(point_1.g())
    print(point_2.g())

if (__name__ == "__main__"):
    main()

And here my output :

borg created
toto
Traceback (most recent call last):
File "file1.py", line 32, in
main()
File "file1.py", line 23, in main
point_1 = Point(5,2)
File "file1.py", line 16, in init
print (self.latitude)
AttributeError: 'Point' object has no attribute 'latitude'

I am surely making a basic mistake un python, but i am not sure of why my "Point" don't have a "latitude" attribute here.

I rode about inheritence and Borg conception, but something is missing. I also try the -tt option for indentation mistake.

CodePudding user response:

Try to put super().__init__() as first instruction in __init__() method of class Point:

class BorgSingleton:
    _shared_borg_state = {}
    test = "toto"

    def __init__(self):
        self.__dict__ = self._shared_borg_state
        print("borg created")
        print(self.test)


class Point(BorgSingleton):

    def __init__(self, lat, long):
        super().__init__()
        self.latitude = lat
        self.longitude = long
        #super().__init__()
        print(self.latitude)

    def g(self):
        return BorgSingleton.test   " "   str(self.latitude)   " "   str(self.longitude)


def main():
    point_1 = Point(5, 2)
    point_2 = Point(3, 3)
    print(point_1.g())
    print(point_2.g())
    point_1.test = "tata"
    print(point_1.g())
    print(point_2.g())


if (__name__ == "__main__"):
    main()

CodePudding user response:

The code you've wrote should've worked if self.__dict__ had not been overridden in the parent BorgSingleton class.

In Python, it is not a good practice to override magic methods (ones that start and end with double-unders) unless you know what you're doing.

To generalize what happened, lets see the below two classes:

class Parent:
    some_attribute = {}

    def __init__(self):
        self.__dict__ = self.some_attribute


class Child(Parent):
    def __init__(self, arg_1, arg_2):
        self.arg_1 = arg_1
        self.arg_2 = arg_2
        # at this point, an instance of class Child has arg_1 and arg_2
        # attributes, and self.__dict__ stores corresponding values
        super().__init__()
        # in the Parent class, self.__dict__ is overridden to an empty dict 
        # which makes arg_1 and arg_2 arguments unaccessible from the 
        # instance after a super call


test_instance = Child(1, 2)

To make your code work, I suggest you remove self.__dict__ redefinition. Also, on line point_1.test = "tata" I assume you intended to redefine test attribute of point_1 instance. However, in Point.g method you access BorgSingleton.test attribute, instead of Point.test attribute, which is available after you call super().__init__() in Point.__init__. After all, the below code should work as you've expected:

class BorgSingleton:
    _shared_borg_state = {}
    test = "toto"


class Point(BorgSingleton):
    def __init__(self, lat, long):
        self.latitude = lat
        self.longitude = long
        super().__init__()

    def g(self):
        return ' '.join((self.test, str(self.latitude), str(self.longitude)))


def main():
    point_1 = Point(5, 2)
    point_2 = Point(3, 3)
    print(point_1.g())
    print(point_2.g())
    point_1.test = "tata"
    print(point_1.g())
    print(point_2.g())


if __name__ == "__main__":
    main()

  • Related