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