Kraigolas
Kraigolas

Reputation: 5560

How does Python differentiate between static and instance attributes?

When I see a python class defined like

class Apple():
    count = 0 

I see count to be a static attribute associated with Apple that can be accessed when writing Apple.count.

I came across an interesting example in one of my courses that doesn't disprove the above, but instead adds some ambiguity:

class Apple():
    count = None 
    def __init__(self, count):
      Apple.count = count

    def get_count(self):
      return self.count

Here, count is defined like a static attribute, and it is even assigned like one. In fact, it is a static attribute! However, it is returned via self.count which to me opposes the typical nature of the python nature. I would expect an error here to tell me that my instance of Apple has no attribute count, because if I run:

a = Apple(6)
b = Apple(8)
print(a.get_count(), b.get_count())
# 8 8 

We can see that get_count() is actually returning the static attribute value count accessed through Apple.count.

My question is, why does python work this way? I always thought that self was tied to a particular instance of the class, but this behavior suggests that self.count is identical to Apple.count unless self.count is shadowed by writing self.count = 10 or some other value. Is there any value to this behaviour in Python?

Upvotes: 1

Views: 41

Answers (1)

quamrana
quamrana

Reputation: 39354

In this case here:

class Apple():
    count = None 
    def __init__(self, count):
      Apple.count = count

    def get_count(self):
      return self.count

count is declared as a class attribute, however the __init__() overwrites this each time an instance is created. You have seen that the last created instance sets the value for all instances

Another thing about class attributes is that they are visible when accessing like: return self.count.

However, if you also had this method:

    def set_count(self, value):
        self.count = value

then each instance will get their own attribute count but only when this is called on that instance.

There is a value to this if you want instances to be initialised with the same value and it is extremely rare for any instance to need a different value, then the class attribute is set once when the class is compiled. Compare this with an __init__() setting Apple.count = 0 for every instance. This could slow down your program and worse, if you did self.count = 0, would take up lots of space when you start creating millions of instances.

Upvotes: 1

Related Questions