Python面向对象编程(六)--多态
https://py.qizhen.xyz/iterator1.python构造函数和析构函数2.python抽象类和接口3.python类多态一、关于多态1.继承和多态2.使用父类引用调用子类的方法3.内置多态4.运算符多态5.参数多态6.抽象基类实现多态二、多态案例案例一多态的基本使用class Animal:def speak(self):passclass Dog(Animal):def speak(self):return 汪汪汪class Cat(Animal):def speak(self):return 喵喵喵def mak_sound(animal:Animal):#animal:Animal其中animal为对象Animal为类并且:Animal可以省略print(animal.speak())dog Dog()#mak_sound(Dog())mak_sound(dog)###mak_sound的参数是要传输对象而不是类所以这里要使用Dog()等价于mak_sound(Dog())mak_sound(Cat())或者class Dog(Animal):def speak(self):return 汪汪汪class Cat(Animal):def speak(self):return 喵喵喵def mak_sound(animal):#animal:Animalprint(animal.speak())dog Dog()#mak_sound(Dog())mak_sound(dog)###mak_sound的参数是要传输对象而不是类所以这里要使用Dog()等价于mak_sound(Dog())mak_sound(Cat())案例二class Bird:def fly(self):return 我是鸟类我在天空中飞翔...class Penguin(Bird):def fly(self):return 我是企鹅我不会飞翔但是我会游泳...class Sparrow(Bird):def fly(self):return 我是一只小麻雀我可以在天空中飞翔...def bird_action(bird:Bird):print(bird.fly())bird_action(Penguin())bird_action(Sparrow())案例三不依赖继承的多态class Duck:def quack(self):return 鸭子嘎嘎嘎...class Person:def quack(self):return 人类模仿鸭子,嘎嘎嘎...def make_quack(obj):print(obj.quack())make_quack(Duck())make_quack(Person())案例四内置函数len()多态#print(len([1, 2, 3])) # 3#print(len(hello)) # 5#print(len({a: 1, b: 2})) # 2class BookCollection:def __init__(self,books):self.books booksdef __len__(self):return len(self.books)BookCollection1 BookCollection([python,java,c])print(len(BookCollection1))BookCollection2 BookCollection(hello)print(len(BookCollection2))BookCollection3 BookCollection({a: 1, b: 2})print(len(BookCollection3))案例五运算符的多态print(10 5) # 15print(Hello World) # Hello Worldprint([1, 2] [3, 4]) # [1, 2, 3, 4]class Vector:def __init__(self,x,y):self.x xself.y ydef __add__(self,other):return Vector(self.x other.x,self.y other.y)def __repr__(self):return fVector({self.x},{self.y})v1 Vector(1,2)v2 Vector(3,4)print(v1 v2)案例六class Circle:def __init__(self,radius):self.radius radiusdef area(self):return 3.14*self.radius**2class Square:def __init__(self,side):self.side sidedef area(self):return self.side**2def print_area(shape):print(f面积为:{shape.area()})print_area(Circle(5))print_area(Square(4))案例七使用抽象基类ABC强制多态契约说明Abstract Base Class,ABC抽象类Abstract Base Class,ABC;通过abc模块来是实现。from abc import ABC,abstractmethod#定义一个抽象类class Payment(ABC):#抽象类的抽象方法abstractmethoddef pay(self,amount):pass #抽象类的抽象方法在子类中必须要进行实现#信用卡支付class CreditCardPayment(Payment):def pay(self,amount):return f使用信用卡支付{amount}元class AlipayPayment(Payment):def pay(self,amount):return f使用阿里支付宝{amount}def checkout(payment_method:Payment,amount):print(payment_method.pay(amount))checkout(CreditCardPayment(),100)checkout(AlipayPayment(),200)案例八定义一个迭代类class Countdown:def __init__(self,start):self.start startdef __iter__(self):n self.startwhile n 0:yield n ###yield n表示产生n的意思n - 1for num in Countdown(10):print(num)案例九上下文管理器多态with 语句#任何实现了__enter__和__exit__的对象都能用于with#文件打开类class FileOpener:def __init__(self,filename,mode):self.filename filenameself.mode modedef __enter__(self):self.file open(self.filename,self.mode)return self.filedef __exit__(self,exc_type,exc_val,exc_tb):self.file.close()#连接数据库类class DatabaseConnection:def __enter__(self):print(建立数据库的连接)return selfdef __exit__(self,*args):print(关闭数据库的连接)def query(self,sql):print(f数据库的查询{sql})with FileOpener(test.txt,w) as f:f.write(hello)with DatabaseConnection() as db:db.query(SELECT * FROM users)案例十property 的多态不同类实现相同属性接口property 装饰器可以将方法“伪装”成属性并且支持继承与重写从而实现多态。class TemperatureCelsius:def __init__(self, celsius):self._celsius celsiuspropertydef temp(self):return self._celsiustemp.setterdef temp(self, value):self._celsius valueclass TemperatureFahrenheit:def __init__(self, fahrenheit):self._fahrenheit fahrenheitpropertydef temp(self):return (self._fahrenheit - 32) * 5/9temp.setterdef temp(self, celsius_value):self._fahrenheit celsius_value * 9/5 32def show_temp(temp_obj):# 不管对象是摄氏度类还是华氏度类都通过 .temp 属性获取值print(f当前温度: {temp_obj.temp:.1f}°C)c TemperatureCelsius(25)f TemperatureFahrenheit(77)show_temp(c) # TemperatureCelsius当前温度: 25.0°Cshow_temp(f) # TemperatureFahrenheit当前温度: 25.0°C