Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

why does the instance have no attribute?

Tags:

python

class Test():    
       myVersion="1.0" 
t=Test()   
t.myVersion    
--> 1.0

Test.myVersion="2.0"  
Test.x={'myVersion':'1.0'}
Test.x  
--> {'myVersion': '1.0'}

t.x 
--> {'myVersion': '1.0'}

del t.x
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: Test instance has no attribute 'x'

Why has the instance t no attribute x?
{'myVersion': '1.0'} is not the attribution?

like image 906
showkey Avatar asked Feb 17 '23 19:02

showkey


2 Answers

In Python, both class and instance attributes are accessible from an instance.

Ref Class instances in http://docs.python.org/2/reference/datamodel.html clarifies how this works -

A class instance is created by calling a class object (see above). A class instance has a namespace implemented as a dictionary which is the first place in which attribute references are searched. When an attribute is not found there, and the instance’s class has an attribute by that name, the search continues with the class attributes.

You can see your class and instance's namespace using Test.__dict__ and t.__dict__ respectively.

Interestingly, if you modify a class attribute by referencing it from the instance, the class attribute will remain unaffected. Instead, a copy of the attribute with the change will be added to the instance's namespace.

For example,

>>> t = Test()  
>>> t.myVersion = "2.0"  
>>> Test.__dict__
{'__module__': '__main__', 'myversion': '1.0', '__doc__': None}
>>> t.__dict__
{'myVersion': '2.0'}

myVersion attribute is now present in both Test (class) and t (instance)'s namespace, and can be safely deleted from either without raising an AttributeError.

The basic idea is that a variable you are trying to delete from an object should be present in its namespace.

like image 91
sidi Avatar answered Feb 20 '23 10:02

sidi


The problem is that the variable isn't attached to the instance, it's attached to the whole class. To fix this, you have to physically attach it (ok, maybe not physically, but you get what I mean) to the instance.

class Test:
    def __init__(self):
        self.myVersion = '1.0'

Then you can delete it.

t = Test()
del t.myVersion  # no exception raised
like image 32
Volatility Avatar answered Feb 20 '23 10:02

Volatility