一、继承:
继承(Inheritance)我叫小王,我爸是大王。继承的本质是个性对共性的属性与方法的接收,并加入个性特有的属性与方法。
一个类继承另一个类,则称继承的类为子类、派生类、衍生类,被继承的类为父类、基类。通过继承实现代码的复用,达到延续和扩展父类信息。继承后子类自动拥有了父类的属性和方法,子类根据需要新增和重写自己特有的属性和方法,实现功能的扩展。
1、理解
继承的本质在于抽象。类是对对象的抽象,继承是对某一批类的抽象,从而实现对现实世界更好的建模。同时使用继承可以提高代码的复用性。(事实上,利用组合可以更好的实现代码复用!)
1class Parent:
2 money = 1000
3 job = '房地产'
4
5 def __init__(self):
6 print("初始化父类。。。")
7
8
9class Child(Parent):
10 job = ''
11
12 def __init__(self,job):
13 self.job = job
14 print("初始化子类。。。")
15
16 def __str__(self):
17 return '属性:"%s", %s' % (self.job, self.money)
18
19c = Child('电竞')
20print(c)
运行结果:
1初始化子类。。。
2属性:"电竞", 1000
2、判断子类
使用issubclass(cls, A_tuple)判断是否为某一个类的子类,其中cls 就是要判断的是否为A_tuple中类的衍生类或者同类,A_tuple可以是一个元组,也可以是一个元素,为父类的元组,A_tuple中有一个类是cls的父类则返回True。
1class A:
2 pass
3class B(A):
4 pass
5class C(B):
6 pass
7class D(B):
8 pass
9
10print(issubclass(B, A), issubclass(C, A))
3、私有信息访问限制
如果子类方法想要访问父类的私有属性和方法时,是不能直接访问的,只能通过调用父类方法访问
1class Parent:
2 def __init__(self, name):
3 self.__name = name # 私有属性
4 def __drinking(self): # 私有方法
5 print("%s爱抽烟。。" % self.__name)
6 def get_name(self):
7 return self.__name
8class Children(Parent):
9 pass
10c = Children("小明")
11#print(c.__name) # 会报 no attribute错误
12# c.__drinking() # 会报 no attribute错误
13print(c.get_name())
4、方法重写
方法重写就是当父类的方法不能满足业务时,就可以通过子类重写父类的方法达到效果,而不需要修改父类方法。在Python中重写就是覆盖父类方法,那么我们在调用时都会遵循就近原则。
1class Father:
2 name = ''
3 age = 0
4 def eat(self):
5 print("爸爸吃一碗!")
6class Son(Father):
7 def eat(self):
8 print("儿子吃一盆!")
9def main():
10 s = Son()
11 s.eat()
12if __name__ == '__main__':
13 main()
Son类重写了Father的eat方法,当main方法调用eat方法时,会优先考虑自己本类的方法,如果没有才会去寻找父类方法。如:
1class Father:
2 name = ''
3 age = 0
4 def __init__(self, name, age):
5 self.name = name
6 self.age = age
7 def study(self):
8 print("%s在看python指南!" % self.name)
9 self.sing()
10 def sing(self):
11 print("爸爸在唱精忠报国")
12class Son(Father):
13 def sing(self):
14 print("%s在唱夏洛特烦恼" % self.name)
15def main():
16 s = Son("大锤", 18)
17 s.study()
18if __name__ == '__main__':
19 main()
二、多态
多态(polymorphism)是很多面向对象编程语言的重要特性,尽管我们的python语言中没有多态这一特性,但是不影响我们对这一特性的了解。不要叹息,我们的python语言特价灵活,有更加灵活的鸭子模型。要是我对你说今天会有好事发生。我并没有说好事是什么,这个好事就是模糊的,究竟是什么好事呢?就是今天我们就会将继承、封装、鸭子模型三大特性斩获囊中。
电脑上的USB接口,就是一个多态,凡是实现了这个接口的电子产品如u盘、打印机、手机都可以与电脑对接,在python中,多态更加灵活,只需要一个对象“看起来像鸭子,走起路来像鸭子,那它被认定是只鸭子”即经典的鸭子模型。
1、理解
在同一个方法中,参数不同导致结果不同的现象叫多态。比如定义一个鸟类,在定义百灵鸟类和鹦鹉类,然后在重写fly方法。定义一个方法,如果传入的是百灵鸟类就会打印百灵鸟的fly方法,如果传入鹦鹉打印鹦鹉的fly方法。
1class Bird:
2 def fly(self):
3 print("鸟会飞。。。")
4class Lark(Bird):
5 def fly(self):
6 print("百灵鸟在飞。。。")
7class Parrot(Bird):
8 def fly(self):
9 print("八哥在飞。。。")
10def fly(bird):
11 bird.fly()
12lark= Lark()
13parrot = Parrot()
14fly(lark)
15fly(parrot)
2、实例
王大锤有一个车库,里面有两种车,奔驰和奥迪,那他具体开哪辆呢,就是要到时开车方法里面传入的是什么车,那就开什么车
1import random
2class Car:
3 def __init__(self, color, name):
4 self.color = color
5 self.name = name
6 def run(self):
7 print(self.name + "启动了")
8class Bmw(Car):
9 def __init__(self, color):
10 self.color = color
11 self.name = "宝马"
12class Benz(Car):
13 def __init__(self, color):
14 self.color = color
15 self.name = "奔驰"
16class Carport:
17 def __init__(self):
18 self.cars = []
19 def fill(self, car):
20 self.cars.append(car)
21 def get_car(self):
22 return self.cars[random.randint(0, len(self.cars)-1)]
23class Person:
24 def drive(self, car):
25 print("我在开%s的%s" % (car.color, car.name))
26if __name__ == '__main__':
27 port = Carport()
28 port.fill(Bmw("红色"))
29 port.fill(Benz("黄色"))
30 car = port.get_car()
31 p = Person()
32 p.drive(car)
3、鸭子模型
因为Python是弱类型语言,所以它的多态和其他面向对象语言比如Java不一样,在Java中实现多态必须使用继承,不然编译就会出现类型不符合,而Python本身不会出现这样的情况,因此在实现多态时,并不一定要使用继承,比如刚刚品酒的例子进行修改:
1class MaoTai:
2 @staticmethod
3 def show_advertisement():
4 print("相逢,人生的机缘;相识,人生的财富;相知,人生的感动。 5茅台迎宾酒,迎宾迎天下")
6class WuLiangYe:
7 @staticmethod
8 def show_advertisement():
9 print("中国的五粮液,世界的五粮液!")
10class JianNanChun:
11 @staticmethod
12 def show_advertisement():
13 print("唐时宫廷酒,盛世剑南春")
14class Person:
15 def drink(self, wine):
16 wine.show_advertisement()
17 print("----")
18if __name__ == '__main__':
19 p = Person()
20 p.drink(MaoTai)
21 p.drink(WuLiangYe)
22 p.drink(JianNanChun)
鸭子模型是动态语言的一个特点,意思就是一个对象“看起来像鸭子,走起路来像鸭子,那它被认定是只鸭子”, 就像刚刚品酒,我定义的MaoTai、WuLiangYe、JianNanChun并不需要集成Wine类,只需要在它们三个类中有一个show_ad的方法,那么在Person类中的drink()方法就可以传入这三个不同的类也能达到打印不同的广告词的效果。这个在静态语言中是没法完成的,因为静态语言对参数的类型有严格的限制。也就是讲动态类型语言的变量或者参数不需要声明的原因,都只需要在运行时校验。
4、super()
上面讲到了重写,子类会覆盖父类的方法,但如果你一定要调用父类方法时,怎么办呢?就使用super()调用
1class Father:
2 name = ''
3 age = 0
4 def __init__(self, name, age):
5 self.name = name
6 self.age = age
7 def kungfu(self):
8 print("祖传的咏春拳。。")
9class Son(Father):
10 # 重写父类的方法,但是祖传的咏春还是会的,因此要用super()调用父类
11 def kungfu(self):
12 #super(Son,self).kungfu()
13 super().kungfu()
14 print("会八卦掌、形意拳。。")
15def main():
16 s = Son("小明", 18)
17 s.kungfu()
18if __name__ == '__main__':
19 main()
继承字典类:
1class ObjectDict(dict):
2 def __init__(self, *args, **kwargs):
3 super().__init__(*args, **kwargs)
4 def __getattr__(self, name):
5 return self[name]
6if __name__ == '__main__':
7 object_dict = ObjectDict(price=100.1)
8print(object_dict.price)
来个复杂点的例子:
1class ObjectDict(dict):
2 def __init__(self, *args, **kwargs):
3 super(ObjectDict, self).__init__(*args, **kwargs)
4 def __getattr__(self, name):
5 if isinstance(self[name], dict):
6 return ObjectDict(self[name])
7 return self[name]
8if __name__ == '__main__':
9 object_dict = ObjectDict(b={'name': '高性能MySQL'}, price=100.1)
10 print(object_dict.b, object_dict.b.name)
11 print(object_dict.price)
最后,奉上视频
继承的理解
多态的理解