Reputation: 1992
I am trying to gain a better understanding of class variables
and the @classmethod
decorator in python. I've done a lot of googling but I am having difficulty grasping basic OOP concepts. Take the following class:
class Repository:
repositories = []
repository_count = 0
def __init__(self):
self.update_repositories()
Repository.repository_count += 1
@classmethod
def update_repositories(cls):
if not cls.repositories:
print('appending repository')
cls.repositories.append('twenty')
else:
print('list is full')
a = Repository()
b = Repository()
print(Repository.repository_count)
Output:
appending repository
list is full
2
In the __init__
method, why does self.update_repositories()
successfully call the update_repositories
class method? I thought that self
in this case refers to the instantiated object, not the class?
The code works without using the @classmethod
decorator. Why?
In the __init__
method why do I need to use the keyword Repository
in Repository.repository_count += 1
? Am I doing this correctly or is there a better practice?
Upvotes: 0
Views: 72
Reputation: 1228
A class method can be called either on the class (such as C.f()) or on an instance (such as C().f()). The instance is ignored except for its class. If a class method is called for a derived class, the derived class object is passed as the implied first argument.
The function works without the decorator, but it is not a class method. The cls
and self
parameter names are simply convention. You can put anything in the place of cls
or self
. For example:
class Demo:
def __init__(self):
pass
def instance_method(test):
print(test)
@classmethod
def class_method(test):
print(test)
demo = Demo()
This results in:
demo.instance_method()
>>> <__main__.Demo object at 0x7facd8e34510>
demo.class_method()
>>> <class '__main__.Demo'>
So all non decorated methods in a class are a considered instance
methods and all methods decorated with @classmethod
are
class methods. Naming your parameters cls
, self
or
anything else for that matter does not effect the functionality, but I
would strongly advice sticking with convention.
In your case specifcally removing the @classmethod
decorator turns the method into an instance method and cls
is now actually what self
would normally be, a reference to the class's instance. Since class methods and attributes can be called from an instance cls.update_repositories
still points to the class variable.
Depends on what you are trying to do. Generally if you want to access a class variable or method inside a class, but outside a class method, your approach is correct.
Upvotes: 1