文章目录
- 1.多态
- 2.类继承的多态
- 3.自定义函数的多态
- 4.鸭子类型
- 5.思维导图
1.多态
多态在编程中是一个非常重要的概念,它是指同一个运算符、函数或对象在不同的场景下,具有不同的作用效果,这么一个技能。
我们知道加号(+)和乘号(*)运算符在 Python 被广泛使用,但是它们并非只是单一的用途,比如当两边都是数字的时候,它们执行的是算术运算:
>>> 3 + 5
8
>>> 3 * 5
15
遇到字符串,会变成另一种情况
>>> "Py" + "FishC"
'PyFishC'
>>> "FishC" * 3
'FishCFishCFishC'
执行的是拼接和重复~
这种 “见机行事” 的行为,我们就称之为多态。
除了运算符之外,Python 中有一些函数也是支持多态的,比如 len() 函数,它的功能是获取一个对象的长度:
>>> len("FishC")
5
>>> len(["Python", "FishC", "Me"])
3
>>> len({"name":"小甲鱼", "age":"18"})
2
你看,给它传递一个字符串,它帮你统计字符的个数;给它传递一个列表,它帮你统计列表中元素的个数;给它传递一个字典,它计算的是字典中键的个数。这就是函数的多态性。
多态的好处这样就一目了然了,尽管我们的接口是不变的,但它却可以根据不同的对象执行不同的操作。
2.类继承的多态
Python 允许我们在子类中定义与父类同名的方法。就是如果我们对于父类的某个方法不满意的话,完全是可以在子类中重新定义一个同名的方法进行覆盖,这种做法我们称为重写,这在前面的课程有讲解过了。
重写,其实就是实现类继承的多态:
>>> class Shape:
... def __init__(self, name):
... self.name = name
... def area(self):
... pass
...
>>> class Square(Shape):
... def __init__(self, length):
... super().__init__("正方形")
... self.length = length
... def area(self):
... return self.length * self.length
...
>>> class Circle(Shape):
... def __init__(self, radius):
... super().__init__("圆形")
... self.radius = radius
... def area(self):
... return 3.14 * self.radius * self.radius
...
>>> class Triangle(Shape):
... def __init__(self, base, height):
... super().__init__("三角形")
... self.base = base
... self.height = height
... def area(self):
... return self.base * self.height / 2
...
>>> s = Square(5)
>>> c = Circle(6)
>>> t = Triangle(3, 4)
>>> s.name
'正方形'
>>> c.name
'圆形'
>>> t.name
'三角形'
>>> s.area()
25
>>> c.area()
113.03999999999999
>>> t.area()
6.0
正方形、圆形、三角形都继承自 Shape 类,但又都重写了构造函数和 area() 方法,这就是多态的体现。
3.自定义函数的多态
>>> class Cat:
... def __init__(self, name, age):
... self.name = name
... self.age = age
... def intro(self):
... print(f"我是一只沙雕猫咪,我叫{self.name},今年{self.age}岁~")
... def say(self):
... print("mua~")
...
>>> class Dog:
... def __init__(self, name, age):
... self.name = name
... self.age = age
... def intro(self):
... print(f"我是一只小狗,我叫{self.name},今年{self.age}岁~")
... def say(self):
... print("哟吼~")
...
>>> class Pig:
... def __init__(self, name, age):
... self.name = name
... self.age = age
... def intro(self):
... print(f"我是一只小猪,我叫{self.name},今年{self.age}岁~")
... def say(self):
... print("oink~") # 不要问我猪为什么这么叫,我是跟隔壁幼儿园的小朋友学的,oink~
...
>>> c = Cat("web", 4)
>>> d = Dog("布布", 7)
>>> p = Pig("大肠", 5)
>>> def animal(x):
... x.intro()
... x.say()
...
>>> animal(c)
我是一只沙雕猫咪,我叫宝儿,今年3岁~
mua~
>>> animal(d)
我是一只小狗,我叫布布,今年5岁~
哟吼~
>>> animal(p)
我是一只小猪,我叫大肠,今年5岁~
oink~
看,这个 animal() 函数就具有多态性,该函数接收不同对象作为参数,并在不检查其类型的情况下执行其方法。
4.鸭子类型
>>> class Bicycle:
... def intro(self):
... print("我曾经跨过山和大海,也穿过人山人海~")
... def say(self):
... print("都有自行车了,要什么兰博基尼?")
...
自行车这个类,既有 intro() 方法,也有 say() 方法,所以它即便被前面的 animal() 函数所调用,也不会出错:
>>> b = Bicycle()
>>> animal(b)
我曾经跨过山和大海,也穿过人山人海~
都有自行车了,要什么兰博基尼?
编程中鸭子类型的概念就是:我们不需要关心对象具体是什么类型,只在乎它的行为方法是否符合要求即可。