Python类多重继承

单继承和多继承:

单继承:每个类只能继承一个类的方式称为单继承。
多继承:每个类可以同时继承多个类的方式称为多继承。

多继承格式:

class 父类1:
    pass

class 父类2:
    pass

class 子类(父类1,父类2):
    pass

注意:当子类继承类多个类的时候,当多个父类的成员方法名不相同时候,则子类都可以进行访问调用,如果多个父类的成员方法的方法名是相同的时候,则当子类调用时候,只按照继承顺序的先后进行调用,调用一次后,不会在调用。

多继承之后,子类就具备了所有父类的成员(私有成员除外)
多个父类具有相同的成员时,子类继承[继承列表]中第一个类的方法

EG1:多重继承

class Base1:
    def fool(self):
        print("我是Bool1")
class Base2:
    def fool(self):
        print("我是Bool2")
class C(Base1, Base2):
    pass
c = C()
c.fool()

 实行结果:

我是Bool1

菱形继承/钻石继承

如果BC类同时继承了A类,D类又继承了BC两个类的情况下(菱形继承),
在调用BC中某个同名方法(该方法都继承自A类)时会导致继承自A类的该方法被多次调用。产生问题

super() 类来解决了多继承的菱形继承问题

补充:

1.uper不是一个关键字,也是不是有函数,他是一个类
2.super()的作用不是查找父类,而是找MRO列表的上一个类
3.super()和父类没有任何实质性的关系,只是有时候能调用到父类而已。
4.在单继承的情况下,super()永远调用的是父类/父对象

类的组合

把类的实例化放到新类里面,一般是把几个不是继承关系的类放到一起(没有纵向关系(继承关系),有横向关系)

补充:一个类的成员变量可以是另一个类的实例化对象(两个类之间没有继承关系)

class Turtle:
    def __init__(self, x):
        self.num = x
class Fish:
    def __init__(self, x):
        self.num = x
class Pool:
    def __init__(self, x, y):
        self.turtle = Turtle(x)
        self.fish = Fish(y)
    def display(self):
        print(self.turtle.num, self.fish.num, sep="\t")
pool = Pool(2,9)
pool.display()

实行结果:2     9

注解:Pool类中的成员变量分别是TurtleFish的实例化对象

程序调用顺序:

1.Pool实例化对象,调用Pool的构造函数,将两个参数传入,在构造函数中,对TurtleFish分别实例化对象,将传入Pool构造函数的两个参数传入到TurtleFish实例化的构造函数中,实例化turtlefish作为Pool的实例化对象pool的成员变量.pool调用display()函数时,又分别访问了turtlefish的成员变量num

补充:

当类之间有显著不同,并且较小的类是较大的类所需要的组件时,用组合比较好

EG:类,类对象,实例对象

class C:
count = 0
a = C()
b = C()
d = C()
print(a.count, b.count, d.count)  # 1
d.count += 10
print(a.count, b.count, d.count)  # 2 修改的是d的实例化对象属性,发生变化的是d的count属性,a和b是分别实例化的它们的值不会修改
C.count = 100
print(a.count, b.count, d.count)  # 3 修改的是类C的静态属性值,a和c没对其实例化属性修改过,而d之前对实例化对象的属性赋值,覆盖了类的静态属性

实行结果:
0 0 0
0 0 10
100 100 10

EG:2实例化对象的属性和方法相同,则属性覆盖方法

class A:
def display(self):
    print("AAAAA")
a = A()
a.display()
a.display = 1 #python中对象不需要声明,直接赋值就是定义。给实例化对象a的display属性直接赋值,该属性和方法名相同,则属性名直接将方法名覆盖掉
a.display()

实行结果:

AAAAA

Python中约定俗成的规定:

1.不要试图在一个类里定义所有能想到的特性和方法,应该利用继承和组合机制进行拓展

2.用不同的词性命名,如属性名用名词,方法名用动词

绑定

定义:python严格要求方法需要有实例才能被调用,这种限制就是绑定

EG1:

class A:
    def display():
        print("AAAAA")
A.display()  # 类对象A直接调用displa方法不会报错
a = A()
a.display()  # 实例化对象a直接调用display方法会报错,因为调用display时把a当作参数传进去了,完整的调用方法a.display(a)

实行结果:

AAAAA

EG2:

class CC:
    def setXY(self, x, y):
        self.x = x
        self.y = y
    def printXY(self):
        print(self.x, self.y)
dd = CC()
print("dd:dict", dd.__dict__)  # 查看对象所有的属性,返回一个字典的类型。字典中只有实例对象的属性,不显示类属性和特殊属性(魔术方法)
print("CC:dict", CC.__dict__)  # 键表示属性名,值就是属性的值
dd.setXY(4, 6)
print("dd:dict", dd.__dict__)  # 这x,y只属于dd这个实例化对象
print("CC:dict", CC.__dict__)  # 类属性中,没有4和6,这归功于绑定,实例化对象dd调用setxy(4,5)实际上将自身当作参数传入进去,完整的函数是dd.setxy(dd,4,6),在函数中赋值是dd.x = 4,dd.y = 6,所以4,6只属于dd
del CC
# ee = CC()  # 出错,类对象已经删除
dd.printXY()

实行结果:

dd:dict {}

CC:dict {'__module__': '__main__', 'setXY': <function CC.setXY at 0x00000000029D7598>, 'printXY': <function CC.printXY at 0x00000000029D7620>, '__dict__': <attribute '__dict__' of 'CC' objects>, '__weakref__': <attribute '__weakref__' of 'CC' objects>, '__doc__': None}

dd:dict {'x': 4, 'y': 6}

CC:dict {'__module__': '__main__', 'setXY': <function CC.setXY at 0x00000000029D7598>, 'printXY': <function CC.printXY at 0x00000000029D7620>, '__dict__': <attribute '__dict__' of 'CC' objects>, '__weakref__': <attribute '__weakref__' of 'CC' objects>, '__doc__': None}

4 6

注意:类中定义的属性和方法是静态变量,就算类对象被删除了,它们还是存放在内存中,只有在程序退出时候,它们才会被释放。(建议编程时使用实例属性,不要使用类属性)

 

 

 

 

 

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值