Python静态类方法(转载)

1. 静态类方法@staticmethod和@classmethod的关系

1.1. 基础介绍

class MyClass:
    def method(self):
        return 'instance method called', self

    @classmethod
    def classmethod(cls):
        return 'class method called', cls

    @staticmethod
    def staticmethod():
        return 'static method called'
  • 实例方法
    MyClass调用的第一个方法method是常规实例方法。这是您大多数时候会使用的基本,简洁的方法类型。您可以看到该方法采用一个参数,self该参数指向MyClass该方法被调用的时间的实例(但当然实例方法可以接受多个参数)。

通过该self参数,实例方法可以自由访问同一对象上的属性和其他方法。在修改对象状态时,这赋予了他们很多功能。

实例方法不仅可以修改对象状态,而且还可以通过self.class属性访问类本身。这意味着实例方法也可以修改类状态。

  • 类方法classmethod

让我们将其与第二种方法进行比较MyClass.classmethod。我用@classmethod装饰器标记了此方法,以将其标记为类方法。

self类方法不接受参数,而是在调用方法时使用cls指向类的参数,而不是对象实例。

因为类方法只能访问此cls参数,所以它不能修改对象实例状态。那将需要访问self。但是,类方法仍然可以修改适用于该类所有实例的类状态。

  • 静态方法staticmethod

第三种方法MyClass.staticmethod用@staticmethod装饰器标记,以将其标记为静态方法。

这种类型的方法既不带参数self也不带cls参数(但是可以自由接受任意数量的其他参数)。

因此,静态方法无法修改对象状态或类状态。静态方法在可以访问哪些数据方面受到限制-它们主要是为方法命名空间的一种方法。

1.2. staticmethod和@classmethod区别

一般来说,要使用某个类的方法,需要先实例化一个对象再调用方法。
而使用@staticmethod或@classmethod,就可以不需要实例化,直接类名.方法名()来调用。
这有利于组织代码,把某些应该属于某个类的函数给放到那个类里去,同时有利于命名空间的整洁。

既然@staticmethod和@classmethod都可以直接类方法名()来调用,那他们有什么区别呢?从它们的使用上来看,@staticmethod不需要表示自身对象的self和自身类的cls参数,就跟使用函数一样。
@classmethod也不需要self参数,但第一个参数需要是表示自身类的cls参数。

如果在@staticmethod中要调用到这个类的一些属性方法,只能直接类名.属性名或类名.方法名。而@classmethod因为持有cls参数,可以来调用类的属性,类的方法,实例化对象等,避免硬编码。案例如下:

class A(object):  
    bar = 1  
    def foo(self):  
        print( 'foo' )  

    @staticmethod  
    def static_foo():  
        print( 'static_foo' ) 
        print( A.bar)  

    @classmethod  
    def class_foo(cls):  
        print('class_foo' ) 
        print( cls.bar)  
        cls().foo()  
###执行  
A.static_foo()  
A.class_foo()

结果:

static_foo
1
class_foo
1
foo

事实上,就是不用对象调用,而是直接用类来调用。Python类中普通方法调用自身的静态方法,使用self.函数名()即可。

案例如下:

In [5]: import numpy as np
   ...: 
   ...: class A(object):
   ...:     def foo(self):
   ...:         self.static_foo()
   ...: 
   ...:     @staticmethod
   ...:     def static_foo():
   ...:         print( 'This is static_foo.')
   ...: 
   ...: if __name__ == "__main__":
   ...:     test = A()
   ...:     test.foo()
   ...: 
This is static_foo.

结果:

This is static_foo.

2. Python三种类方法案例

  • 静态方法(staticmethod)
  • 类方法(classmethod)
  • 实列方法
  • 代码实现:
class TestFuc(object):
    def instance_fuc(self, x):
        print('instance_fuc(%s,%s)' % (self, x))

    @classmethod
    def class_fuc(cls,x):
        print('class_fuc(%s,%s)' % (cls,x))

    @staticmethod
    def static_fuc(x):
        print('static_fuc(%s)' % x)

test_fuc = TestFuc()

# 实例方法
test_fuc.instance_fuc(1)
# 类方法
test_fuc.class_fuc(1)
TestFuc.class_fuc(1)

# 静态方法
test_fuc.static_fuc(1)
TestFuc.static_fuc(1)

执行结果:

instance_fuc(<__main__.TestFuc object at 0x0000017EFA10DFC8>,1)
class_fuc(<class '__main__.TestFuc'>,1)
class_fuc(<class '__main__.TestFuc'>,1)
static_fuc(1)
static_fuc(1)

3. 继承类中的区别

  • 子类的实例继承了父类的static_method静态方法,调用该方法,还是调用的父类的方法和类属性。
  • 子类的实例继承了父类的class_method类方法,调用该方法,调用的是子类的方法和子类的类属性。

源码:

class Foo(object):
    X = 1
    Y = 2

    @staticmethod
    def averag(*mixes):  #一种变量代替多变量
        return sum(mixes) / 1

    @staticmethod
    def static_method():
        return Foo.averag(Foo.X, Foo.Y)

    @classmethod
    def class_method(cls):
        return cls.averag(cls.X, cls.Y)

class Son(Foo):
    X = 3
    Y = 5

    @staticmethod
    def averag(*mixes):
        return sum(mixes) / 2

p = Son()
print(p.static_method())
print(p.class_method())

结果:

3.0
4.0

4. 参考

静态类方法@staticmethod和@classmethod

发表评论

邮箱地址不会被公开。 必填项已用*标注