一:继承
1,面向对象中的继承表示的是类与类之间的关系(什么是什么的关系),在python3中,所有的类都会默认继承object类,继承了object类的所有类都是新式类,如果一个类没有继承任何父类,那么__bases__属性就会显示<class ‘object‘>。
2,继承可以分为单继承和多继承。
# 单继承 class Parent:pass class Son(Parent):pass # 继承关系 # Son继承了Parent print(Son.__bases__) # 内置的属性 print(Parent.__bases__) # 内置的属性 # 多继承 class Parent1:pass class Parent2(Parent1):pass class Parent3:pass class Son(Parent2,Parent3):pass # 继承关系 print(Parent2.__bases__) print(Son.__bases__)
3,对象使用名字的顺序: 先找对象自己内存空间中的,再找对象自己类中的,再找父类中的。
class Animal: role = ‘Animal‘ def __init__(self,name,hp,ad): self.name = name # 对象属性 属性 self.hp = hp #血量 self.ad = ad #攻击力 def eat(self): print(‘%s吃药回血了‘%self.name) class Person(Animal): r = ‘Person‘ def attack(self,dog): # 派生方法 print("%s攻击了%s"%(self.name,dog.name)) def eat2(self): print(‘执行了Person类的eat方法‘) self.money = 100 self.money -= 10 self.hp += 10 class Dog(Animal): def bite(self,person): # 派生方法 print("%s咬了%s" % (self.name, person.name)) # 继承中的init alex = Person(‘alex‘,10,5) print(Person.role) print(alex.__dict__) dog = Dog(‘teddy‘,100,20) print(dog.__dict__) # 继承中的派生方法 alex = Person(‘alex‘,10,5) dog = Dog(‘teddy‘,100,20) alex.attack(dog) dog.bite(alex) # 继承父类的方法:自己没有同名方法 alex = Person(‘alex‘,10,5) dog = Dog(‘teddy‘,100,20) alex.eat2() alex.eat() dog.eat()
# class Animal: # def __init__(self,name,sex,kind): # self.name = name # self.sex = sex # self.kind = kind # def eat(self): # print(‘%s is eating‘%self.name) # # def drink(self): # print(‘%s is drinking‘%self.name) # # class Cat(Animal): # def climb(self): # print(‘%s is climbing‘%self.name) # # class Dog(Animal): # def watch_door(self): # print(‘%s is watching door‘%self.name) # 1.确认自己没有init方法 # 2.看看有没有父类 # 3.发现父类Animal有init # 4.看着父类的init方法来传参数 #tom = Cat(‘tom‘,‘公‘,‘招财猫‘) # 实例化对象 # tom.eat = ‘猫粮‘ # print(Cat.__dict__) # Cat.__dict__ Cat类的命名空间中的所有名字 # print(tom.__dict__) # tom.__dict__ 对象的命名空间中的所有名字 # tom.eat() # 先找自己对象的内存空间 再找类的空间 再找父类的空间 # tom.climb() # 先找自己的内存空间 再找类的空间
4,self.名字的时候,不要看self当前在哪个类里,要看这个self到底是谁的对象
class Parent: def func(self): print(‘in parent func‘) def __init__(self): self.func() class Son(Parent): def func(self): print(‘in son func‘) s = Son()
5,object 类
class A: # ‘‘‘ # 这是一个类 # ‘‘‘ pass a = A() print(A.__dict__) # 双下方法 魔术方法 # 创建一个空对象 # 调用init方法 —— 调用了么? 调用了 # 将初始化之后的对象返回调用处
6,在单继承中,如何给一个类的对象增加派生属性呢?
详见如下代码:
class Animal: def __init__(self,name,hp,ad): self.name = name # 对象属性 属性 self.hp = hp #血量 self.ad = ad #攻击力 def eat(self): print(‘eating in Animal‘) self.hp += 20 class Person(Animal): def __init__(self,name,hp,ad,sex): # Animal.__init__(self,name,hp,ad) #次为方法一 # super(Person,self).__init__(name,hp,ad) #此为方法二 super().__init__(name, hp, ad) #此为方法二简写(常用) # 在单继承中,super负责找到当前类所在的父类,在这个时候不需要再手动传self self.sex = sex # 这个就是增加的派生属性 self.money = 100 def attack(self,dog): # 派生方法 print("%s攻击了%s"%(self.name,dog.name)) def eat(self): # 重写 super().eat() # 在类内 使用 super()方法找父类的方法 print(‘eating in Person‘) self.money -= 50 class Dog(Animal): def __init__(self,name,hp,ad,kind): Animal.__init__(self,name,hp,ad) self.kind = kind # 派生属性 def bite(self,person): # 派生方法 print("%s咬了%s" % (self.name, person.name)) alex = Person("zhangsan",100,10,"male") # 实例化 #print(alex.__dict__) # tg = Dog(‘到哥‘,100,50,‘藏獒‘) # print(tg.__dict__) # 父类有eat 子类没有 # alex.eat() # 找父类的 # 子类有eat 不管父类中有没有 # alex.eat() # 找子类的 # 当子类中有,但是我想要调父类的 # Animal.eat(alex) #指名道姓 # super(Person,alex).eat() # super(子类名,子类对象)方法 —— 一般不用 # 子类父类都有eat方法,我想执行父类的eat和子类的eat #alex.eat() # 执行子类的eat
7,多继承之钻石继承
对于多继承中的新式类,寻找名字的顺应该遵循广度优先。类名.mro() 可以查询广度优先的遍历顺序。
例如下面的程序:
class A: def func(self): print(‘A‘) class B(A): pass # def func(self): # print(‘B‘) class C(A): pass # def func(self): # print(‘C‘) class D(B): pass # def func(self): # print(‘D‘) class E(B,C): pass # def func(self): # print(‘E‘) class F(D,E): pass # def func(self): # print(‘F‘) f = F() f.func() print(F.mro()) # 查看广度优先的遍历顺序,其遍历顺序为 F-D-E-B-C-A
【附】:pyrhon3 中的新式类遵循的广度优先算法图示
8,当遇到多继承和super时,应遵循以下的情况:
(1)找到这个对象对应的类。
(2)将这个类的所有父类都找到画成一个图
(3)根据图写出广度优先的顺序
(4)再看代码,看代码的时候要根据广度优先顺序图来找对应的super
例如以下程序:
class A: def func(self): print(‘A‘) class B(A): def func(self): super().func() print(‘B‘) class C(A): def func(self): super().func() print(‘C‘) class D(B,C): def func(self): super().func() print(‘D‘) d = D() d.func() #结果为 A-C-B-D
该程序分析过程如下:
【注】:supper(),在单继承中就是单纯的寻找父类,在多继承中就是根据子节点所在图的 mro 顺序找寻下一个类。
9,python 2中的经典类的多继承问题
【注】:经典类只在 python2 版本才存在,且必须不继承object。它在遍历的时候遵循深度优先算法,而且没有mro方法和super()方法。在python2 的版本中,必须手动继承object 类,才是新式类。它在遍历的时候遵循广度优先算法,在新式类中,有mro方法和super()方法,但是在2.X版本的解释器中,必须传参数(子类名,子类对象)。
【附】:python2 中的经典类中遵循的深度优先算法图示
原文地址:https://www.cnblogs.com/leiwei123/p/8809196.html