面向对象
组合
概念:一个对象的属性值,是另外一个类的对象
单继承
概念
新式类(object类)
python3中特有的,没有父类的类会默认继承object
当一个类没有继承父类时,实际他默认就继承了object类。所以下面两种写法是一样的效果 class A: pass class A(object): pass
父类
也叫超类,基类
一个类可以被多个类继承
如何定义一个父类? class A: pass
子类
也叫派生类
一个类可以继承多个类(只有python支持)
继承时如果子类有的方法/属性,就会调用子类的。如果子类没有则会调用父类的
定义一个子类,继承A class B(A): pass
__init__方法在继承中的功能
如果一个子类没有自己的init方法。当子类对象调用一个子类没有的属性/方法时,会先在子类找,子类没有再去父类找。
#使用子类对象调用父类的属性 class Animal: def __init__(self,name,aggr,hp): self.name = name self.aggr = aggr self.hp = hp class Dog(Animal): pass d = Dog('大黄',5,10)#子类不需要这些参数,但是父类需要,所以还得传 print(d.name)#通过子类的对象调用父类的属性
如果一个子类有自己的init方法。当子类对象调用一个子类没有的属性/方法时。就不会再往父类找了。可以在子类的init方法中以父类名.__init__(self,父类需要的参数)的方式解决这个问题。代码如下,第11行的写法。
1 class Animal: 2 def __init__(self,name,aggr,hp): 3 self.name = name 4 self.aggr = aggr 5 self.hp = hp 6 7 class Dog(Animal): 8 def __init__(self,name,aggr,hp,kind): 9 #把父类需要的参数全部传过去,并且self也需要传。传过去的self是子类的self。 10 # 子类的self在父类赋值(初始化)之后,就包含了父类的属性。 11 Animal.__init__(self,name,aggr,hp) 12 self.kind = kind 13 #此时的self既包含了父类的属性,也包含了子类的属性
派生属性
什么是派生属性:父类中没有的属性,在子类中出现,叫做派生属性
1 class Animal: 2 def __init__(self,name,aggr,hp): 3 self.name = name 4 self.aggr = aggr 5 self.hp = hp 6 7 class Dog(Animal): 8 def __init__(self,name,aggr,hp,kind): 9 Animal.__init__(self,name,aggr,hp) 10 self.kind = kind #kind只有子类有,父类没有。这个self.kind就叫派生属性 11 12 d = Dog('大黄',5,10,11) 13 print(d.kind)#调用派生属性 14 15 结果:11
派生方法
什么是派生方法:父类中没有的方法,在子类中出现,叫做派生方法
class Animal: def __init__(self,name,aggr,hp): self.name = name self.aggr = aggr self.hp = hp class Dog(Animal): def ww(self): print('这是个派生方法') d = Dog('大黄',5,10) d.ww()
结果:这是个派生方法
用子类的对象,调用子类中有的属性/方法,一定用子类的,子类中没有才会找父类的。如果父类没有会报错
class Animal: def __init__(self,name,aggr,hp): self.name = name self.aggr = aggr self.hp = hp def ww(self): print('这是父类的方法') class Dog(Animal): def __init__(self,name,aggr,hp): Animal.__init__(self,name,aggr,hp) self.name = '小黄' def ww(self): print('这是子类的方法') d = Dog('大黄',5,10) d.ww() print(d.name) 这是子类的方法 小黄 #这是子类的属性name
如果子类和父类都有的方法,想用父类的,怎么使用?
在第13行,通过父类名去调用
1 class Animal: 2 def __init__(self,name,aggr,hp): 3 self.name = name 4 self.aggr = aggr 5 self.hp = hp 6 def ww(self): 7 print('这是父类的方法') 8 class Dog(Animal): 9 def __init__(self,name,aggr,hp): 10 Animal.__init__(self,name,aggr,hp)#调用类名的init方法,将子类的self传给父类进行赋值 11 self.name = '小黄' 12 def ww(self): 13 Animal.ww(self)#在子类中使用:父类名.方法名(self,参数)就可以调用父类中和子类重名的方法 14 print('这是子类的方法') 15 d = Dog('大黄',5,10) 16 d.ww()#这里一定会执行子类的ww方法。但是在子类的ww方法中做了处理,可以调到父类的ww,再执行剩下的代码 17 18 结果:这是父类的方法 19 这是子类的方法
super
新式类里面的关键字:super。只有在python3中可以使用.
super方法在类中使用
1 class Animal: 2 def __init__(self,name,aggr,hp): 3 self.name = name 4 self.aggr = aggr 5 self.hp = hp 6 def ww(self): 7 print('这是父类的方法') 8 class Dog(Animal): 9 def __init__(self,name,aggr,hp): 10 #Animal.__init__(self,name,aggr,hp) 11 super().__init__(name,aggr,hp)#这里的super就和上面用类名操作是基本一样的效果。只是在传参的时候,少传了一个self。 12 self.name = '小黄' 13 def ww(self): 14 Animal.ww(self)#在子类中使用:父类名.方法名(self,参数)就可以调用父类中和子类重名的方法 15 print('这是子类的方法') 16 17 d = Dog('大黄',5,10) 18 d.ww()#这里一定会执行子类的ww方法。但是在子类的ww方法中做了处理,可以调到父类的ww,再执行剩下的代码 19 20 结果: 21 这是父类的方法 22 这是子类的方法
super方法在类外面使用
class Animal: def __init__(self,name,aggr,hp): self.name = name self.aggr = aggr self.hp = hp def ww(self): print('这是父类的方法') class Dog(Animal): def __init__(self,name,aggr,hp): #Animal.__init__(self,name,aggr,hp) super().__init__(name,aggr,hp) self.name = '小黄' def ww(self): print('这是子类的方法') d = Dog('大黄',5,10) super(Dog,d).ww()#super(子类名,子类对象名).方法名()。这样写也可以在父类和子类重名的时候,调到父类的方法。 结果:这是父类的方法
__bases__双下方法
print(类型A.__bases__)#打印A继承的所有父类
多继承
1.优先使用离子类最近的父类的方法
2.广度优先规则 python3和python2中的新式类使用
3.深度优先规则 python2中的经典类使用
从第一个父类,往上找。一直找到最上层,没有再找第二个父类,往上找。已经找过的就不再找了。
y小知识点:
python2支持新式类和经典类,继承了object类的就叫新式类
python3只有新式类,默认继承object
查看继承顺序用mro方法(只在新式类中可以使用).mro
面试题
当一个子类和父类同时拥有一个同名的方法,且子类没有自己的__init__方法时。在父类中__init__方法中调用同名的方法。结果是调用子类的,而不是调用父类的。