4

There is a code:

class C():
    a=1
    def f(self):
        print "f func"

a=C()
print a.a
a.f()
>>> 1
>>> f func

And when i trying to get a.__dict__ or vars(a), it shows me just {}. But

a.b=123
print a.__dict__
>>> {'b': 123}

I don't understand, why it is.

Zeugma
  • 31,231
  • 9
  • 69
  • 81
EgorPuzyrev
  • 119
  • 1
  • 8

2 Answers2

4

Looking at a.__dict__ or vars(a) gives you attributes of a, which is an instance. That instance initially has no attributes of its own. The attribute a that you created in your class definition is an attribute of the class itself, not of its instances. Later when you do a.b = 123, you create an attribute just on the instance, so you can see it in the instance __dict__. You will see the attribute a if you look at C.__dict__.

When you do print a.a, Python dynamically finds the attribute a on the class C. It sees that the instance doesn't have an attribute a, so it looks on the class and finds one there. That is the value that is printed. The class attribute is not "copied" to the instance when the instance is created; rather, every individual time you try to read the instance attribute, Python checks to see if it exists on the instance, and if not it looks it up on the class.

BrenBarn
  • 242,874
  • 37
  • 412
  • 384
2
>>> C.a
1
>>> vars(C)['a']
1

(The whole vars dictionary for a class is rather long.)

Like your title says, it's a class variable. It belongs to the class, not the object. Python is doing some special logic behind the scenes to look on the type object for you when you call a.a. I'm not an expert, but I suspect it's finding a the same way it would find a method. In languages such as Java, I believe this sort of usage is discouraged. I don't know if it's discouraged in Python.

jpmc26
  • 28,463
  • 14
  • 94
  • 146