Python 类方法,静态方法,实例方法
类方法,静态方法,实例方法都可以通过类名和实例对象访问,如下:
需要注意点一点是类名访问实例方法的时候必须传递实例对象。
注意:函数 只能由类名访问(Python3),Python2不能访问。
注意:申明静态方法使用@staticmethod 并且不用加类名或者实例对象作为参数
注意:申明类方法使用@classmethod 并且需要加上cls作为方法参数
class A(object):
@classmethod
def cls_func(cls):
print "classmethod"
@staticmethod
def static_func():
print("staticmethod")
def instance_func(self):
print("instance_func")
def common_func():
print("common func")
a = A()
a.cls_func()
a.static_func()
a.instance_func()
A.cls_func()
A.static_func()
A.instance_func(a)
#Error python2 中类名不能访问函数,但是Python3可以访问
#A.common_func()
#Error Python2/3中都不能使用实例访问函数
#a.common_func()
>>classmethod
staticmethod
instance_func
classmethod
staticmethod
instance_func
common func
子类中访问父类的方法,以及多重继承的问题
在python中子类访问父类的方法有两种方式:
1.使用类名调用类的方法:
class A(object):
def __init__(self):
print("Call A __init__!")
class B(A):
def __init__(self):
print("Call B __init__!")
A.__init__(self)
b = B()
>>Call B __init__!
Call A __init__!
2.使用super调用父类的方法:
class A(object):
def __init__(self):
print("Call A __init__!")
class B(A):
def __init__(self):
print("Call B __init__!")
super(B, self).__init__()
b = B()
>>Call B __init__!
Call A __init__!
方法一更直观。推荐使用方法一进行父类的初始化。
注意!注意!注意!这里纠正一下:有的地方说方法二可以一次初始化所有超类,该说法是错误的。super并不是像Java或者其他语言一样调用所有父类的构造方法,它是调用的__class__.mro()
的下一个类调用构造方法 如下:
下面的函数并不会调用B类的构造函数,因为__class__.mro()
指向的下一个类是A。
class A(object):
def __init__(self, age=1):
print("A __init__!")
self.age = age
class B(object):
def __init__(self, name=""):
print("B __init__!")
self.name = name
class C(A,B):
def __init__(self):
print("C __init__!")
super(C, self).__init__()
c = C()
>>C __init__!
A __init__!
[<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>]
就算调用两次super也不会初始化B的构造函数,如下:
反而它只是调用了两次A类的构造函数而已。
class A(object):
def __init__(self, age=1):
print("A __init__!")
self.age = age
class B(object):
def __init__(self, name=""):
print("B __init__!")
self.name = name
class C(A,B):
def __init__(self):
print("C __init__!")
super(C, self).__init__()
super(C, self).__init__()
c = C()
>>C __init__!
A __init__!
A __init__!
[<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>]
下面列举一个更加复杂的例子来说明:
class A(object):
def __init__(self, age=0):
print("A __init__!")
self.age = age
print("A leaving!")
class B(A):
def __init__(self, name=""):
print("B __init__!")
super(B, self).__init__()
self.name = name
print("B leaving!")
class C(A):
def __init__(self):
print("C __init__!")
super(C, self).__init__()
print("C leaving !")
class D(B, C):
pass
d = D()
print(d.__class__.mro())
如果是想当然以为super是调用父类的构造函数那么输出的顺序应该是
>>B __init__!
A __init__!
A leaving!
B leaving!
C __init__!
A __init__!
A leaving!
C leaving !
然而情况是:当调用D的初始化函数时按照D类的mro()顺序来选择下一个类的初始化。
这里还可以看出如果你没有写__init__
函数,那么python默认的方式是通过super初始化父类
>>B __init__!
C __init__!
A __init__!
A leaving!
C leaving !
B leaving!
[<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <type 'object'>]
结论是:当你的程序里面含有多重继承存在的时候千万要注意尽量避免使用super的方式,而应该直接使用类名初始化的方式,多写几行代码比出错来的划算!上面的例子改写为方法一的方式如下:
class A(object):
def __init__(self, age=0):
print("A __init__!")
self.age = age
print("A leaving!")
class B(A):
def __init__(self, name=""):
print("B __init__!")
A.__init__(self, age=12)
self.name = name
print("B leaving!")
class C(A):
def __init__(self):
print("C __init__!")
A.__init__(self, age=14)
print("C leaving !")
class D(B, C):
def __init__(self):
print("D __init__!")
B.__init__(self)
C.__init__(self)
print("D leaving!")
d = D()
>>D __init__!
B __init__!
A __init__!
A leaving!
B leaving!
C __init__!
A __init__!
A leaving!
C leaving !
D leaving!
Python mro 的顺序问题
首先mro是按照深度优先的计算方式,重复类只保留最后一个,这是什么意思呢?就拿上面的例子来说深度优先的原则的话就应该是[D, B, A, object, C, A, object] 这样一个顺序,但是重复类只保留最后一个的原则决定了它应该是[D, B, C, A, object]这样的。所以这样就很好的理解了super为什么会表现出那样的方式。
下面再给出一个例子说明:
class A(object):
def __init__(self, age=0):
print("A __init__!")
self.age = age
print("A leaving!")
def func(self):
print("A func call!")
class B(A):
def __init__(self, name=""):
print("B __init__!")
A.__init__(self, age=12)
self.name = name
print("B leaving!")
class C(A):
def __init__(self):
print("C __init__!")
A.__init__(self, age=14)
print("C leaving !")
def func(self):
print("C func call!")
class D(B, C):
def __init__(self):
print("D __init__!")
B.__init__(self)
C.__init__(self)
print("D leaving!")
d = D()
d.func()
>>D __init__!
B __init__!
A __init__!
A leaving!
B leaving!
C __init__!
A __init__!
A leaving!
C leaving !
D leaving!
C func call!
以上程序的输出是C func 被调用了,也证实了mro的顺序规则。