views:

91

answers:

4

This is a completely theoretical question. Suppose the following code:

>>> class C:
...     a = 10
...     def f(self): self.a = 999
...
>>>
>>> C.a
10
>>> c = C()
>>> c.a
10
>>> c.f()
>>> c.a
999

At this point, is class variable C.a still accessible through the object c?

+4  A: 

Yes, though c.__class__.a or type(c).a. The two differ slightly in that old-style classes (hopefully, those are all dead by now - but you never know...) have a type() of <type 'instance'> (and __class__ works as expected) while for new-style classes, type() is identical to __class__ except when the object overrides attribute access.

delnan
+1  A: 

All class variables are accessible through objects instantiated from that class.

>>> class C:
...     a = 10
...     def f(self): self.a = 999
... 
>>> C.a
10
>>> c = C()
>>> c.a
10
>>> c.f()
>>> c.a
999
>>> c.__class__.a
10
>>> c.a
999
>>> del(c.a) 
>>> c.a
10

Attributes are first searched within the object namespace and then class.

pyfunc
+1  A: 

Yes, you can access a from an object c, à la c.a. The value would initially be 10.

However, if you call c.f(), the value of c.a will now be 999, but C.a will still be 10. Likewise, if you now change C.a to, say, 1000, c.a will still be 999.

Basically, when you instantiate an instance of C, it will use the class variable as its own a value, until you change the value of that instance's a, in which case it will no longer "share" a with the class.

mipadi
+1  A: 

After you assign to it on the class instance, there is both a class attribute named a and an instance attribute named a. I illustrate:

>>> class Foo(object):
...     a = 10
... 
>>> c = Foo()
>>> c.a
10
>>> c.a = 100  # this doesn't have to be done in a method
>>> c.a   # a is now an instance attribute
100
>>> Foo.a  # that is shadowing the class attribute
10
>>> del c.a  # get rid of the instance attribute
>>> c.a     # and you can see the class attribute again
10
>>> 

The difference is that one exists as an entry in Foo.__dict__ and the other exists as an entry in c.__dict__. When you access instance.attribute, instance.__dict__['attribute'] is returned if it exists and if not then type(instance).__dict__['attribute'] is checked. Then the superclasses of the class are checked but that gets slightly more complicated.

But at any rate, the main point is that it doesn't have to be one or the other. A class and an instance can both have distinct attributes with identical names because they are stored in two separate dicts.

aaronasterling
This is the clearest explanation here. Thanks for a good answer.
Paul McMillan