弄了好久都感觉自己没弄懂 先记录一点自己懂的吧
单继承:
在单继承中 super
就像大家所想的那样,主要是用来调用父类的方法的。
代码示例:
class A:
def __init__(self):
self.n = 2
def add(self, m):
print('self is {0} @A.add'.format(self))
self.n += m
class B(A):
def __init__(self):
self.n = 3
def add(self, m):
print('self is {0} @B.add'.format(self))
super().add(m)
self.n += 3
b = B()
b.add(2)
print(b.n)
结果:
结论:
- 1、super().add(m) 确实调用了父类 A 的 add 方法。
- 2、super().add(m) 调用父类方法 def add(self, m) 时, 此时父类中 self 并不是父类的实例而是子类的实例, 所以 b.add(2) 之后的结果是 5 而不是 4 。
多继承:
class A:
def __init__(self):
self.n = 2
def add(self, m):
print('self is {0} @A.add'.format(self))
self.n += m
class B(A):
def __init__(self):
self.n = 3
def add(self, m):
print('self is {0} @B.add'.format(self))
super().add(m)
self.n += 3
class C(A):
def __init__(self):
self.n = 4
def add(self, m):
print('self is {0} @C.add'.format(self))
super().add(m)
self.n += 4
class D(B, C):
def __init__(self):
self.n = 5
def add(self, m):
print('self is {0} @D.add'.format(self))
super().add(m)
self.n += 5
d = D()
d.add(2)
print(d.n)
结果:
原理图:
会涉及到查找顺序(MRO)、重复调用(钻石继承)等种种问题。
我啥也不懂 我就背住好了~
1、Python 的子类也会继承得到父类的构造方法,但如果子类有多个直接父类,那么会优先选择排在最前面的父类的构造方法
代码:
class Employee :
def __init__ (self, salary):
self.salary = salary
def work (self):
print('普通员工正在写代码,工资是:', self.salary)
class Customer:
def __init__ (self, favorite, address):
self.favorite = favorite
self.address = address
def info (self):
print('我是一个顾客,我的爱好是: %s,地址是%s' % (self.favorite, self.address))
# Manager继承了Employee、Customer
class Manager (Employee, Customer):
pass
m = Manager(25000)
m.work() #①
#m.info() #②
结果:
解释:该类继承了 Employee 和 Customer 两个父类。接下来程序中的 Manager 类将会优先使用 Employee 类的构造方法(因为它排在前面),所以程序使用 Manager(25000)来创建 Manager 对象。该构造方法只会初始化 salary 实例变量,因此执行上面程序中 ① 号代码是没有任何问题的。
但是当执行到 ② 号代码时就会引发错误,这是由于程序在使用 Employee 类的构造方法创建 Manager 对象时,程序并未初始化 Customer 对象所需的两个实例变量:favorite 和 address,因此程序引发错误。
同样的 如果继承的顺序相反了的话 那么②号代码可以执行 但是①号代码无法执行 那么有什么方法可以解决这种问题呢?
为了让 Manager 能同时初始化两个父类中的实例变量,Manager 应该定义自己的构造方法,即重写父类的构造方法。Python 要求,如果子类重写了父类的构造方法,那么子类的构造方法必须调用父类的构造方法。
子类的构造方法调用父类的构造方法有两种方式:
1.使用未绑定方法,这种方式很容易理解。因为构造方法也是实例方法,当然可以通过这种方式来调用。
2.使用 super() 函数调用父类的构造方法。
注意,当子类继承多个父类时,super() 函数只能用来调用第一个父类的构造方法(也就是先继承到的那个父类),而其它父类的构造方法只能使用未绑定的方式调用。
实现代码:
class Employee :
def __init__ (self, salary):
self.salary = salary
def work (self):
print('普通员工正在写代码,工资是:', self.salary)
class Customer:
def __init__ (self, favorite, address):
self.favorite = favorite
self.address = address
def info (self):
print('我是一个顾客,我的爱好是: %s,地址是%s' % (self.favorite, self.address))
# Manager继承了Employee、Customer
class Manager(Employee, Customer):
# 重写父类的构造方法
def __init__(self, salary, favorite, address):
print('--Manager的构造方法--')
# 通过super()函数调用父类的构造方法
super().__init__(salary)
# 与上一行代码的效果相同
#super(Manager, self).__init__(salary)
# 使用未绑定方法调用父类的构造方法
Customer.__init__(self, favorite, address)
# 创建Manager对象
m = Manager(25000, 'IT产品', '广州')
m.work() #①
m.info() #②
上面程序中 分别示范了两种方式调用父类的构造方法。通过这种方式,Manager 类重写了父类的构造方法,并在构造方法中显式调用了父类的两个构造方法执行初始化,这样两个父类中的实例变量都能被初始化。
参考文章:http://c.biancheng.net/view/2290.html