#在Python的多继承中,如果子类继承的多个父类中包含了同名的方法,子类在调用时会选择哪个

class Item : def info (self): print("Item中的方法","这是一个商品")class Product: def info(self): print("Product中的方法" , "这是一个工业产品")class Mouse(Item, Product): passm = Mouse()m.info()

输出:
Item中的方法,这是一个商品

class Item : def info (self): print("Item中的方法","这是一个商品")class Product: def info(self): print("Product中的方法" , "这是一个工业产品")class Mouse(Product, Item): passm = Mouse()m.info()

输出:
Product中的方法 这是一个工业产品
总结:
可见多继承中,父类有同名方法,子类在调用时会选择继承中排在前面的父类方法
拓展:
如果子类也包含同名方法,子类调用同名方法,优先选择自己的方法,这叫做重写,也叫覆盖override

class Item : def info (self): print("Item中的方法","这是一个商品")class Product: def info(self): print("Product中的方法" , "这是一个工业产品")class Mouse(Item, Product): def info(self): print("这是一个鼠标")m = Mouse()m.info()

输出:
这是一个鼠标

拓展1:

如果在多继承中子类和父类方法同名了,父类方法被子类方法覆盖了,但是我仍然想要调用父类的方法,那该怎么办?


Python 类相当于类空间,因此Python 类中的方法本质上相当于类空间内的函数。
所以,即使是实例方法, Python 也允许通过类名调用。区别在于: 在通过类名调用实例方法时,Python 不会为实例方法的第一个参数self 自动绑定参数值,而是需要程序显式绑定第一个参数self。这种机制被称为未绑定方法。


再看代码:

# 在Python的多继承中,如果子类继承的多个父类中包含了同名的方法,子类在调用时会选择哪个 class Item : def info (self): print("Item中的方法","这是一个商品")class Product: def info(self): print("Product中的方法" , "这是一个工业产品")class Mouse(Item, Product): def info(self): print("这是一个鼠标") def all_method(self): self.info() #子类的info方法 Item.info(self) #Item父类的info方法 Product.info(self) #Product父类的info方法m = Mouse()m.all_method()

输出结果:
这是一个鼠标
Item中的方法 这是一个商品
Product中的方法 这是一个工业产品
这说明通过这种方法所有的info方法都被调用了

拓展2:

使用super函数调用父类的构造方法
因为构造方法是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))class Manger(Employee, Customer): passm = Manger(5000) #子类继承的是父类Employee的构造方法m.work() #m.info() #出错,因为info中使用了Customer中定义的构造属性,但是子类并没有从Customer中继承favorite, address属性

所以构造方法很特殊,因为他为对象初始化了属性,这些属性在其他方法中被使用,如果在子类继承中不继承父类的init方法,那么复用父类的一些方法,就会出现错误,继承的最大有点就是复用,如果不能复用,那么继承毫无意义,所以我们必须在子类中重写父类的构造方法,继承所有父类的init方法,同时也可以扩展子类的属性。继承父类的init方法有两种:

使用未绑定方法, 这种方式很容易理解。因为构造方法也是实例方法, 当然可以通过这种方式来调用。使用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))# class Manager(Employee, Customer):# pass## m = Manager(5000) #子类继承的是父类Employee的构造方法# m.work() ## m.info() #出错,因为info中使用了Customer中定义的构造属性,但是子类并没有从Customer中继承favorite, address属性class Manager(Employee, Customer): def __init__(self, salary, favorite, address, occupation): #重写init,要写所有父类中的init属性,同时可以添加子类的属性occupation self.occupation = "new add" print("这是Manager类的构造方法") # 继承Employee中的init方法,super方法,两种写法都可以 # super().__init__(salary) #super写法1 super(Manager, self).__init__(salary) #super写法2 # 继承Customer方法,通过调用未绑定的方法,显式传递self Customer.__init__(self, favorite, address) print("我是子类Manager 初始化方法init中定义的属性:", self.occupation)m = Manager(5000, 'sing', 'china', 'IT')m.work()m.info()