smwikipedia
smwikipedia

Reputation: 64175

Strange behaviors of instance variables in Python 2.7 OOP

My code:

>>> class Class1:
    pass

>>> obj1=Class1()
>>> obj2=Class1()
>>> obj1.x1=123
>>> obj2.x2=456

Then I got the following errors:

>>> obj1.x2

Traceback (most recent call last):
  File "<pyshell#9>", line 1, in <module>
    obj1.x2
AttributeError: Class1 instance has no attribute 'x2'

And similarly:

>>> obj2.x1

Traceback (most recent call last):
  File "<pyshell#11>", line 1, in <module>
    obj2.x1
AttributeError: Class1 instance has no attribute 'x1'

The AttributeError is quite strange, why it says the Class1 has no attribute 'x1' and 'x2'? Python claims to be able to add fields on the fly. And I am expecting result like this:

obj1.x2 = None
obj2.x1 = None

What's the difference between the field add on the fly and the contained in the class definition?

Upvotes: 0

Views: 57

Answers (2)

Bleeding Fingers
Bleeding Fingers

Reputation: 7129

What's the difference between the field add on the fly and the contained in the class definition?

This is in class definition:

>>> class Class1:
    x = None

Proof:

>>> Class1().__dict__
{}
>>> Class1.__dict__
{'x': None, '__module__': '__main__', '__doc__': None}

This at instance level:

>>> class Class1:
    def __init__(self):
    self.x = None

Proof:

>>> Class1.__dict__
{'__module__': '__main__', '__doc__': None, '__init__': <function __init__ at 0x000000000241C358>}
>>> Class1().__dict__
{'x': None}

Adding attribute on the fly adds the attribute at the instance level not the class level

Proof:

>>> class Class1: pass
... 
>>> foo = Class1()
>>> foo.__dict__
{}
>>> foo.x = None
>>> foo.__dict__
{'x': None}
>>> Class1.__dict__
{'__module__': '__main__', '__doc__': None}

You can add attributes to class definition on the fly too.

Proof:

>>> class Class1: pass
... 
>>> Class1.__dict__
{'__module__': '__main__', '__doc__': None}
>>> Class1().__dict__
{}
>>> Class1.x = None
>>> Class1.__dict__
{'x': None, '__module__': '__main__', '__doc__': None}
>>> Class1().__dict__
{}
>>> Class1().x
>>> print Class1().x
None

Upvotes: 1

Jakob Bowyer
Jakob Bowyer

Reputation: 34688

If obj1 is an instance of Class1 then it is adding variables on an instance-based level.

This can be seen as below

class Test(object): pass 
a = Test()
b = Test()
a.a = 4
print a.a
print b.a # Attribute error here.

If you mean to add a class level variable, apply this to Test directly

Test.a = 432
print b.a
print a.a

Upvotes: 3

Related Questions