Python instance methods, class methods, and static methods


0. Reference materials

  • Python’s Instance, Class, and Static Methods Demystified

1. An overview

Start by defining the simplest Python 3 class:

class MyClass:
    def method(self) :
        print('I'm an instance method', self)

    @classmethod
    def classmethod(cls) :
        print('I'm a class method', cls)

    @staticmethod
    def staticmethod() :
        print('I'm a static method')
Copy the code

1.1 Example Method

The first method method(self) method is the instance method. When method is called, the self argument points to an instance of the MyClass class. Instance methods have free access to properties of the same object and other methods through Self so that they can modify the state of the instance. Note that instance methods can get the class via the self.__class__ attribute, so instance methods can also change the state of the class.


1.2 class method

The second method classMethod (CLS) is the classmethod. I need to put an @ classMethod decorator on it. A class method takes a CLS parameter that refers to the class (not the instance of the class) when the method is called. A class method has only CLS parameters, so it cannot modify the state of the instance. Modifying the state of an instance must have the self argument. Class methods can only modify the state of a class, and changes in class state apply to all instances of that class.


1.3 Static Method

The third method staticmethod() is a staticmethod. It should have an @StaticMethod decorator on it. A static method cannot modify the state of a class or instance; it is limited by the parameters it receives. We usually use this method to isolate namespaces.


2. Practical application

2.1 Calling instance methods

First create an instance and call the instance method:

obj = MyClass()

Call the instance method
obj.method()
""" I am the instance method <__main__.MyClass Object at 0x00000213E209B898> ""
Copy the code

It can also be called:

MyClass.method(obj)
""" I am the instance method <__main__.MyClass Object at 0x00000213E209B898> ""
Copy the code

Using object.instance method () the dot call form is a syntactic sugar, and Python automatically passes the object as the first argument to the self parameter in the instance method. If you use the form class.instance method (object), you must manually pass the object to the first argument to the instance method, self.

If you call the instance method without creating the instance, or pass in no object, you get an error:

What happens if you call the instance method without creating the instance?
# will prompt that the positional argument self is missing
The instance method depends on the instance
MyClass.method()
""" Traceback (most recent call last): File "test.py", line 28, in 
      
        MyClass.method() TypeError: method() missing 1 required positional argument: 'self' """
      
Copy the code

Instance methods can access classes through self.__class__.

Print the class name
print(obj.__class__.__name__)
"""
MyClass
"""
Copy the code

2.2 Calling class methods

Let’s call the class method.

Call class methods by class name
MyClass.classmethod(a)# also automatically passes the class name as the first argument
""" I am a class method 
      
        """
      
Copy the code

By calling a class method as class.class method (), Python automatically passes the class as the first argument to CLS, the first argument to the class method.

Class methods can also be called with instances:

Class methods can also be called by instance
obj.classmethod(a)""" I am a class method 
      
        """
      
Copy the code

Using an instance to call a class method, Python passes that instance’s class to the CLS parameters of the class method, not necessarily the class that defines the class method. The following cases:

# the parent class
class Animal:
    @classmethod
    def classmethod(cls) :
        print('CLS is:' + str(cls.__name__))


# subclass
class Dog(Animal) :
    pass


dog = Dog()
dog.classmethod(a)""" CLS is: Dog ""
# notice that this is not the definition of a class method: Animal
# It is the instance's class: Dog

Copy the code

2.3 Calling a Static Method

Finally, call the static method:

Call static methods
obj.staticmethod(a)""" I'm a static method """
When static methods are called
The dot syntax does not automatically pass any arguments
Copy the code

When static methods are called, Python does not pass self and CLS to limit the permissions of static methods. So static methods cannot get the state of an instance or class. They are just like normal functions, but belong to the namespace of the class and each instance of that class.


2.4 Call method without creating instance

Instead of creating an instance, call instance methods, class methods, and static methods.

Call class method instead of creating instance
MyClass.classmethod(a)""" I am a class method 
      
        """
      

Call static method instead of creating instance
MyClass.staticmethod(a)""" I'm a static method """

Instead of creating an instance, call the instance method
MyClass.method()
""" Traceback (most recent call last): File "test.py", line 85, in 
      
        MyClass.method() TypeError: method() missing 1 required positional argument: 'self' """
      
Copy the code

Failed to create instance, calling instance method. This is understandable because we call instance methods directly from the class blueprint itself, and Python cannot pass arguments to self.


3. Implement the pizza factory using class methods

class Pizza:
    def __init__(self, ingredients) :
        self.ingredients = ingredients

    def __repr__(self) :
        return F 'pizza ({self.ingredients}) '

    @classmethod
    def margherita(cls) :
        return cls(['Mozzarella'.'tomato'])

    @classmethod
    def prosciutto(cls) :
        return cls(['Mozzarella'.'tomato'.'the ham'])
Copy the code

Use class methods as factory functions to produce different kinds of pizzas.

A factory function is a function that creates and returns different objects based on different inputs.

Notice that in the factory function, instead of using the Pizza class name directly, the CLS parameter is used. This has the advantage of being easy to maintain. In case you need to change the Pizza class name to Pizza in the future, just make one change because the class method uses CLS instead of writing the class name directly. This is a tip to follow the DRY principle (Don’t repeat Yourself)

Now use the factory function to generate a few pizzas:

pizza1 = Pizza.margherita()
print(pizza1)
Pizza ([' Mozzarella, ' 'tomato ']) """

pizza2 = Pizza.prosciutto()
print(pizza2)
Pizza ([' Mozzarella, ' 'tomato,' 'ham ']) ""
Copy the code

We can use factory functions to create pre-configured Pizza objects. These factory functions all use the __init__ constructor internally, which provides a shortcut to remembering various pizza recipes. From another perspective, these class methods can define multiple constructors for a class.


4. When to use static methods

Rewrite the Pizza class above.

import math


class Pizza:
    def __init__(self, radius, ingredients) :
        self.radius = radius
        self.ingredients = ingredients

    def __repr__(self) :
        return (F 'pizza ({self.radius! r}), '
                f'{self.ingredients! r}) ')

    def area(self) :
        return self.circle_area(self.radius)

    @staticmethod
    def circle_area(r) :
        return r ** 2 * math.pi
Copy the code

Try using static methods:

# Generate pizza
p = Pizza(4['Mozzarella'.'tomato'])
print(p)
Pizza (4, [' Mozzarella ', 'tomato ']) """

# Calculate the area of the pizza
p.area()
print(p.area())
"" "50.26548245743669 "" "

Call a static method from a class
print(Pizza.circle_area(4))
"" "50.26548245743669 "" "

Call static methods from objects
print(p.circle_area(4))
"" "50.26548245743669 "" "
Copy the code

The benefits of writing a method as static:

  • Indicates that it does not change the state of the class or instance
  • It is easier to write test code that tests static methods without instantiating them

5. To summarize

  • To call the instance method, you need an instance. Instance methods can get instances through self.

    • Instance methods are called by instance without having to manually pass the instance toself.
    • To call an instance method from a class, you need to manually pass the instance toself.
  • Class methods can be called by instance or class. Class methods can get the class itself through CLS. Class methods are decorated with an @ classMethod decorator.

    • Class methods are called by instance without having to manually pass the class tocls. Class methods called by instance,PythonAutomatic pass toclsIs the class to which the object belongs, not necessarily the class that defines its methods. For example, a parent class defines a class method, and a subclass inherits from the parent class. The class method of the parent class is called by an instance of the subclassclsThe arguments in the class are subclasses, not the parent classes that define class methods.
    • Class methods are called through classes without having to manually pass classes tocls.
  • Static methods can be called by instance or class.

Static methods cannot fetch CLS and self. Static methods should be decorated with @staticMethod.

  • Class methods and static methods, to some extent, communicate the design intent of a class and make the code easy to maintain.

Completed in 2018.11.24