0

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
  1. 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?

  2. The code works without using the @classmethod decorator. Why?

  3. 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?

1 Answer 1

1
  1. Class methods can be called from an instance. Look at the documentation here.

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.

  1. 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.

  2. 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.

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks for writing this up, it definitely helped clarify things.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.