python3的多继承问题

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

class Item :
    def info (self):
        print("Item中的方法","这是一个商品")

class Product:
    def info(self):
        print("Product中的方法" , "这是一个工业产品")

class Mouse(Item, Product):
    pass

m = Mouse()
m.info()

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

class Item :
    def info (self):
        print("Item中的方法","这是一个商品")

class Product:
    def info(self):
        print("Product中的方法" , "这是一个工业产品")

class Mouse(Product, Item):
    pass

m = 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):
    pass

m = Manger(5000) #子类继承的是父类Employee的构造方法
m.work() #
m.info() #出错,因为info中使用了Customer中定义的构造属性,但是子类并没有从Customer中继承favorite, address属性

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

  1. 使用未绑定方法, 这种方式很容易理解。因为构造方法也是实例方法, 当然可以通过这种方式来调用。
  2. 使用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()

猜你喜欢

转载自blog.51cto.com/13560219/2453833
今日推荐