@(python)
super(type, obj)
子类中定义了同父类同名的函数后,需要显示调用父类函数时,可以通过 super,也可以直接通过父类名,建议使用 super,比如在初始化函数中调用父类初始化方法,尤其在多重继承的情况下
看看例子:
#!/usr/bin/env python
# coding=utf-8
class A:
def __init__(self):
print("Enter A")
super(A, self).__init__()
print("Leave A")
class B:
def __init__(self):
print("Enter B")
#super(B, self).__init__()
print("Leave B")
class CA(A):
def __init__(self):
print("Enter CA")
super(CA,self).__init__()
print("Leave CA")
class CAA(CA, A):
def __init__(self):
print("Enter CAA")
super(CAA,self).__init__()
print("Leave CAA")
class CB(B):
def __init__(self):
print("Enter CB")
B.__init__(self)
print("Leave CB")
class CBB(CB, B):
def __init__(self):
print("Enter CBB")
CB.__init__(self)
B.__init__(self)
print("Leave CBB")
if __name__ == "__main__":
print("- New Object CAA")
caa = CAA()
print("- New Object CBB")
cbb = CBB()
上述列子中,两组类关系:
CAA->CA->A 采用 super 调用父类函数
CBB->CB->B 直接通过父类名调用其行数
对比运行结果
lcd@ubuntu:~/learn/python$ python3 supper_class.py
- New Object CAA
Enter CAA
Enter CA
Enter A
Leave A
Leave CA
Leave CAA
- New Object CBB
Enter CBB
Enter CB
Enter B
Leave B
Leave CB
Enter B -->重复调用了
Leave B
Leave CBB
可以看到,使用super, python 不止保证继承时按顺序调用父类初始化,而且保证每一个类不被重复调用。
classsmethod
python 有三种方式定义类方法:
如下面例子类 A 定义的三个方法,
- 常规方式定义了 foo,同对象实例绑定,通过对象调用的时候,会通过隐式 self 参数传递类对象实例子;如果直接通过类调用,需要显示传递类实例;
- @classmethod 方式定义了 class_foo 方法,同类绑定,可以直接通过类名可以直接调用,调用时通过 cls 隐式参数传递类对象。
- @staticmethod 方式定义的方法和普通函数一样,没有绑定对象,没有传递隐式参,可以通过类实例或者类调用。(属于类的函数,但是不需要访问类,通过后续子类覆盖,更好地组织代码)
#!/usr/bin/env python
# coding=utf-8
# by orientlu
class A(object):
def __init__(self):
print("A init")
super().__init__()
def foo(self, x):
'''绑定对象'''
print("A exec foo (%s, %d)" %(self, x))
@classmethod
def class_foo(cls, x):
'''绑定类'''
print("exec class_foo (%s, %d)" %(cls, x))
@staticmethod
def static_foo(x):
'''没有绑定类,对象'''
print("exec static_foo (%d)" %(x))
class B(object):
def foo(self, x):
'''绑定对象'''
print("exec foo (%s, %d)" %(self, x))
@classmethod
def test_class_foo(cls, x):
'''绑定类'''
print("exec test_class_foo -2- (%s, %d)" %(cls, x))
def test_class_foo(self, x):
'''后面方法覆盖前面的同名方法'''
print("exec test_class_foo -1- (%s, %d)" %(self, x))
class AA(A):
def __init__(self):
print("AA Int")
def foo(self, x):
'''覆盖了父类函数'''
print("AA exec foo (%s, %d)" %(self, x))
class C(AA):
def __init__(self):
'''子类定义了方法覆盖了父类,通过super调用到父类函数'''
super().__init__()
print("C init")
def c_fun1(self):
'''子类没有定义的函数,直接调用父类函数'''
self.foo(1)
if __name__ == "__main__":
print("***********************************")
print("-------")
a = A()
a.foo(1)
a.class_foo(1)
a.static_foo(1)
print("-------")
A.foo(a, 1)
A.class_foo(1)
A.static_foo(1)
print("***********************************")
b = B()
b.test_class_foo(1)
# 以下调用出错,因为classmethod被后面的函数所覆盖了
#B.test_class_foo(1)
# 实际存在是后面定义的函数
B.test_class_foo(b, 1)
print("***********************************")
c = C()
c.c_fun1()
上述代码在 python3 环境下运行的输出 :
***********************************
-------
A init
A exec foo (<__main__.A object at 0x7f6af4c36ac8>, 1)
exec class_foo (<class '__main__.A'>, 1)
exec static_foo (1)
-------
A exec foo (<__main__.A object at 0x7f6af4c36ac8>, 1)
exec class_foo (<class '__main__.A'>, 1)
exec static_foo (1)
***********************************
exec test_class_foo -1- (<__main__.B object at 0x7f6af4c36b38>, 1)
exec test_class_foo -1- (<__main__.B object at 0x7f6af4c36b38>, 1)
***********************************
AA Int
C init
AA exec foo (<__main__.C object at 0x7f6af4c36b70>, 1)
网友评论