Using Static and Class Methods

Today, there is another option for coding simple functions associated with a class that may be called through either the class or its instances. As of Python 2.2, we can code classes with static and class methods, neither of which requires an instance argument to be passed in when invoked. To designate such methods, classes call the built-in functions staticmethod and classmethod, as hinted in the earlier discussion of new-style classes. Both mark a function object as special—i.e., as requiring no instance if static and requiring a class argument if a class method. For example:

class Methods:
    def imeth(self, x):            # Normal instance method: passed a self
        print(self, x)

    def smeth(x):                  # Static: no instance passed
        print(x)

    def cmeth(cls, x):             # Class: gets class, not instance
        print(cls, x)

    smeth = staticmethod(smeth)    # Make smeth a static method
    cmeth = classmethod(cmeth)     # Make cmeth a class method

广告:个人专属 VPN,独立 IP,无限流量,多机房切换,还可以屏蔽广告和恶意软件,每月最低仅 5 美元

Notice how the last two assignments in this code simply reassign the method names smeth and cmeth. Attributes are created and changed by any assignment in a class statement, so these final assignments simply overwrite the assignments made earlier by the defs.

Technically, Python now supports three kinds of class-related methods: instance, static, and class. Moreover, Python 3.0 extends this model by also allowing simple functions in a class to serve the role of static methods without extra protocol, when called through a class.

Instance methods are the normal (and default) case that we’ve seen in this book. An instance method must always be called with an instance object. When you call it through an instance, Python passes the instance to the first (leftmost) argument automatically; when you call it through a class, you must pass along the instance manually (for simplicity, I’ve omitted some class imports in interactive sessions like this one):

>>> obj = Methods()                # Make an instance

>>> obj.imeth(1)                   # Normal method, call through instance
<__main__.Methods object...> 1     # Becomes imeth(obj, 1)

>>> Methods.imeth(obj, 2)          # Normal method, call through class
<__main__.Methods object...> 2     # Instance passed explicitly

By contrast, static methods are called without an instance argument. Unlike simple functions outside a class, their names are local to the scopes of the classes in which they are defined, and they may be looked up by inheritance. Instance-less functions can be called through a class normally in Python 3.0, but never by default in 2.6. Using the staticmethod built-in allows such methods to also be called through an instance in 3.0 and through both a class and an instance in Python 2.6 (the first of these works in 3.0 without staticmethod, but the second does not):

>>> Methods.smeth(3)               # Static method, call through class
3                                  # No instance passed or expected

>>> obj.smeth(4)                   # Static method, call through instance
4                                  # Instance not passed

Class methods are similar, but Python automatically passes the class (not an instance) in to a class method’s first (leftmost) argument, whether it is called through a class or an instance:

>>> Methods.cmeth(5)               # Class method, call through class
<class '__main__.Methods'> 5       # Becomes cmeth(Methods, 5)

>>> obj.cmeth(6)                   # Class method, call through instance
<class '__main__.Methods'> 6       # Becomes cmeth(Methods, 6)