Preamble

Sometimes, programs need to process data associated with classes instead of instances. Consider keeping track of the number of instances created from a class, or maintaining a list of all of a class’s instances that are currently in memory. This type of information and its processing are associated with the class rather than its instances. That is, the information is usually stored on the class itself and processed in the absence of any instance.

Documentation

Fixture

Data model

In order to illustrate the core idea of these built-in functions lets create a incidental but lucid code snippet:

class Vehicle:
    """Naturally it is a vehicle"""

    counter = 0

    def __init__(self, **kwargs):
        """by default all cars are black"""
        Vehicle.counter += 1  # increments the CLASS variable
        # self.counter += 1 - increments the PARTICULAR ITEM VARIABLE
        # the variables below are the particular instance variables
        if kwargs:
            self.color = kwargs['color']
        else:
            self.color = 'black'

    @classmethod
    def get_num_vehicles(cls):
        return cls.counter


class Car(Vehicle):
    """Naturally it is a car properties definition"""

    counter = 0  # it's a class variable

    @staticmethod
    def inc_counter():
        Car.counter += 1

    def get_num_cars():
        """Python3.x interprets any function inside a particular class
        without self argument as a static method"""
        return Car.counter

Mock-up objects creation

my_car = Car(color='red')
alice_car = Car(color='white')
bob_car = Car()

Test the classes' properties

print("Number of cars = %s" % Car.get_num_vehicles()) # accessed from classmethod
print("Number of vehicles = %s" % Vehicle.get_num_vehicles())
print("Parent class counter = %s" % Vehicle.counter) # accessed as a class variable
print("%s cars exists." % (Car.counter))
Number of cars = 0
Number of vehicles = 3
Parent class counter = 3
0 cars exists.

Result analysis

Obviously that we've created three Car objects but our code identified and counted them as Vehicles. Lets try to increment the particular counter in a straightforward manner:

Car.inc_counter()
print("Now there is only %s car there" % Car.counter)
Car.counter += 2 # evaluate the counter directly
print("Now there are %s cars there" % Car.counter)
Now there is only 1 car there
>>> Now there are 3 cars there

In Python 3.*, we need not declare such methods as static if they will be called through a class only, but we must do so in order to call them through an instance.

my_car.inc_counter()
print("There are %s cars" % Car.get_num_cars())
There are 4 cars

Conclusion

Both staticmethod and classmethod

can be called without the instance

self instance argument not passes to them

staticmethod

simple functions with no self argument that are nested in a class and are designed to work on class attributes instead of instance attributes. Static methods never receive an automatic self argument, whether called through a class or an instance. They usually keep track of information that spans all instances, rather than providing behavior for instances.

classmethod

methods of a class that are passed a class object in their first argument instead of an instance, regardless of whether they are called through an instance or a class. Such methods can access class data through their self class argument even if called through an instance. Normal methods (now known in formal circles as instance methods) still receive a subject instance when called; static and class methods do not.



blog comments powered by Disqus

Published

15 September 2016

Categories

python3 stdlib literate programming

Tags