1,复习1python
# 面向对象编程 # 思想:角色的抽象,建立类,建立角色(实例化),操做这些示例 # 面向对象的关键字 class 类名: 静态属性 = 'aaa' def __init__(self):pass 类名.静态属性 # --储存在类的命名空间里 对象 = 类名() # 实例化:创造了一个self对象,执行init方法,返回self对象给外部 # 对象.属性 # 对象.方法 绑定方法,方法和对象绑定到了一块儿 # 类名.方法(对象) # 对象可使用静态变量?True # 类可使用对象里的属性吗?False
2,复习2面试
# 组合 # 一个类的对象是另一个类的属性 # 什么有什么的关系 class A: def __init__(self): self.name = 'egon' class B: def __init__(self,year,month,day): self.year = year self.month = month self.day = day b = B(18,1,17) a = A() a.birth = b print(b.year) # 18 print(a.birth.year) # 18
3,面向对象的三大特性:继承,多态和封装,很是很是重要的,计算机领域的三大特性算法
什么是继承:继承是一种建立新类的方式,在Python中,新建的类能够继承一个或多个父类,父类又可称为基类或超类,新建的类称为派生类或子类编程
class A:pass # 父类,基类,超类 class B:pass # 父类,基类,超类 class A_son(A,B):pass # 子类,派生类 class AB_son(A):pass # 子类,派生类 # 一个类 能够被多个类继承 # 一个类 能够继承多个父类 ----这个只有Python里面才有 print(A_son.__bases__) # (<class '__main__.A'>, <class '__main__.B'>) print(AB_son.__bases__) # (<class '__main__.A'>,) print(A.__bases__) # (<class 'object'>,)
4,类里面,刚开始加载类的时候,就从上到下把类里面的名字加载进去了,加载进去后才能够用类名.静态属性。占内存的也只是里面的变量名字而已设计模式
5,object在类食物链的顶端, python3里面没有继承父类,默认继承object,这种累叫作新式类,object类是一个很是强大的类,里面实现了不少不少的内容,object里面有不少双下方法网络
6,一般的继承都是咱们本身写的类,可是到网络编程的时候,咱们会接触到继承Python里面已经存在的类,例如str等python2.7
7,抽象,抽取相似或者比较像的部分,抽象最主要的做用是划分类别,能够隔离关注点,下降复杂度spa
8,类和类的关系叫作继承,类和对象的关系叫作实例化。设计
class Animal: def __init__(self,name,aggr,hp): self.name = name self.aggr = aggr self.hp = hp class Dog(Animal): def bite(self,person): person.hp -= self.aggr class Person(Animal): pass jin = Dog('bossjin',200,500) # 子类没有__init__方法,会去调用父类的双下init方法 print(jin.name)
9,子类和父类都有的方法,会优先调用谁的呢?这是一道面试题,传谁的self就运行谁的方法。code
class Animal: def __init__(self): print("执行Animal.__init__") self.func() def eat(self): print('%s eating'%self.name) def drinking(self): print("%s dringking"%self.name) def func(self): print("Animal.func") class Dog(Animal): def guard(self): print('guarding') def func(self): print('Dog.func') dog = Dog() # 这儿调用的是Dog类里面的func.由于self传得是dog
运行结果:
执行Animal.__init__
Dog.func
10,对于下面的问题怎么解决呢?
class Animal: def __init__(self,name,aggr,hp): self.name = name self.aggr = aggr self.hp = hp class Dog(Animal): def __init__(self,name,aggr,hp,kind): self.kind = kind def bite(self,person): person.hp -= self.aggr jin = Dog('bossjin',200,500,'teddy') print(jin.name) # AttributeError: 'Dog' object has no attribute 'name' # 错误缘由,本身有了init就不会再去运行父类的init方法,
11,派生属性
class Animal: def __init__(self,name,aggr,hp): self.name = name self.aggr = aggr self.hp = hp class Dog(Animal): def __init__(self,name,aggr,hp,kind): Animal.__init__(self,name,aggr,hp) # 这个地方咱们不只完成了继承,还完成了派生,也就是一个派生属性,新添加的属性 self.kind = kind def bite(self,person): person.hp -= self.aggr jin = Dog('bossjin',200,500,'teddy') print(jin.name) # bossjin
12,除了有派生属性,还有派生方法,父类没有子类有的就是派生方法;父类中没有的属性,在子类中出现,叫作派生属性;父类中没有的方法,在子类中出现,叫作派生方法。
只要是子类的对象调用,子类中有的名字,必定用子类的,子类中没有才找父类的,若是父类也没有,报错;若是父类子类都有,用子类的;若是还想用父类的,单独调用父类的,须要本身传self参数。
13,既想实现新的功能,也想用父类的功能,须要单独调用父类的
class Animal: def __init__(self,name,aggr,hp): self.name = name self.aggr = aggr self.hp = hp def eat(self): print("吃药回血") self.hp += 100 class Dog(Animal): def __init__(self,name,aggr,hp,kind): Animal.__init__(self,name,aggr,hp) # 这个地方咱们不只完成了继承,还完成了派生,也就是一个派生属性,新添加的属性 self.kind = kind # 派生属性 def eat(self): Animal.eat(self) # 若是既想实现新的功能也想使用父类本来的功能,还须要在子类中再调用父类 self.teeth = 2 def bite(self,person): # 派生方法 person.hp -= self.aggr jin = Dog('bossjin',200,500,'teddy') jin.eat() print(jin.teeth)
14,另一个调用父类方法的Python3中的用法,super,类内和类外均可以用,内部能够不传参,外部必传
class Animal: def __init__(self,name,aggr,hp): self.name = name self.aggr = aggr self.hp = hp def eat(self): print("吃药回血") self.hp += 100 class Dog(Animal): def __init__(self,name,aggr,hp,kind): super().__init__(name,aggr,hp) # self 不须要单独传了,super()意思是找个人父类,而后就能够调用父类的init了 # 这个地方省略了两个参数 Dog类和self对象两个参数 # super关键字只要新式类中有,不是Python3,Python中全部的类都是新式类,Python2中两种类共存 # super还能够再类外面用 self.kind = kind def eat(self): Animal.eat(self) self.teeth = 2 print('son class') def bite(self,person): person.hp -= self.aggr jin = Dog('bossjin',200,500,'teddy') jin.eat() print(jin.teeth) super(Dog,jin).eat() # 这儿调用的是父类的eat方法。
15,子类中调用父类方法两种:父类名.方法名 须要本身传self参数,super().方法名 类内不须要本身传self
16,正常的代码中 单继承 ==减小了代码的重复,继承表达了一种子类是父类的关系,提到组合和继承必定是两个类以上的,看是“是”的关系仍是“有”的关系。例如:老师有生日,狗是动物
17,工做中用的通常都是单继承,多继承通常就是设计模式,或者面试中用到,多继承的继承顺序问题
class A: def func(self):print('A') class B: def func(self):print('B') class C: def func(self): print('C') class D(A,B,C): def func(self): print('D') # 调用顺序 print(D.mro()) # [<class '__main__.D'>, <class '__main__.A'>, <class '__main__.B'>, <class '__main__.C'>, <class 'object'>]
18,钻石继承问题:
class A: def func(self):print('A') class B(A): def func(self):print('B') class C(A): def func(self): print('C') class D(B,C): def func(self): print('D') # 调用顺序 print(D.mro()) # [<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>]
19,Python3里面全部的新式类都是采用广度优先的方式,漏斗,若是后面有机会找到爷爷类,那么就能够广度优先找
# 漏斗 class A: def func(self):print('A') class B(A): def func(self):print('B') class E: def func(self):print('E') class C(E): def func(self): print('C') class D(B,C): def func(self): print('D') # 调用顺序 print(D.mro()) # [<class '__main__.D'>, <class '__main__.B'>, <class '__main__.A'>, <class '__main__.C'>, <class '__main__.E'>, <class 'object'>]
20,小乌龟问题,就是一个六边形,
# 小乌龟 class F: def func(self):print('F') class A(F): def func(self):print('A') class B(A): def func(self):print('B') class E(F): def func(self):print('E') class C(E): def func(self): print('C') class D(B,C): def func(self): print('D') # 调用顺序 print(D.mro()) # [<class '__main__.D'>, <class '__main__.B'>, <class '__main__.A'>, <class '__main__.C'>, <class '__main__.E'>, <class '__main__.F'>, <class 'object'>]
21,get 一个算法,method resolution order mro,新式类,广度优先;经典类是深度优先(一条道走到黑,只要能到就一直走这条道,走到头就走另一条),继承object的类才是新式类,经典类若是直接建立一个类在2.7中就是经典类,深度优先。
22,多继承中,咱们子类的对象调用一个方法,默认是就近原则,经典类中,深度优先,新式类中,广度优先,python2.7新式类和经典类共存,新式类要继承object,python3中只有新式类,默认继承object,经典类和新式类有一个区别super,mro方法只在新式类中存在
23,super的本质,单继承里面永远是父类,只有多继承才会出现同级的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() print(D.mro()) # [<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>] # A # C # B # D # super的本质,不是直接找父类,而是根据调用者的节点位置的广度优先顺序来的