1. 静态类方法@staticmethod和@classmethod的关系
1.1. 基础介绍
1 2 3 4 5 6 7 8 9 10 11 |
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参数,可以来调用类的属性,类的方法,实例化对象等,避免硬编码。案例如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
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() |
结果:
1 2 3 4 5 |
static_foo 1 class_foo 1 foo |
事实上,就是不用对象调用,而是直接用类来调用。Python类中普通方法调用自身的静态方法,使用self.函数名()即可。
案例如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
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. |
结果:
1 |
This is static_foo. |
2. Python三种类方法案例
- 静态方法(staticmethod)
- 类方法(classmethod)
- 实列方法
- 代码实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
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) |
执行结果:
1 2 3 4 5 |
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类方法,调用该方法,调用的是子类的方法和子类的类属性。
源码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
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()) |
结果:
1 2 |
3.0 4.0 |
4. 参考
静态类方法@staticmethod和@classmethod
赞赏微信赞赏
支付宝赞赏