多态与鸭子类型
编写适用于任何兼容对象的多态代码。
第 4 / 4 课14 个步骤
多态与鸭子类型 是 CoddyKit 上的免费 Python Academy 课时。 这是第 4 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Python Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Python Academy 课程共包含 4 节课。
简介
多态允许不同对象响应同一个接口。鸭子类型的含义是:如果一个对象的行为像鸭子,那么它就是鸭子。
什么是多态
多态意味着“多种形式”。同一个方法名可以在不同对象上表现出不同的行为。Python 对此进行了广泛应用。
class Cat:
def speak(self): return 'Meow'
class Dog:
def speak(self): return 'Woof'
for animal in [Cat(), Dog()]:
print(animal.speak())鸭子类型
Python 不要求多态必须依赖类层次结构。只要对象拥有正确的方法,就可以正常工作。无需使用接口。
class Duck:
def quack(self): return 'Quack'
class Person:
def quack(self): return 'I am quacking like a duck'
def make_it_quack(duck):
print(duck.quack())
make_it_quack(Duck())
make_it_quack(Person())多态函数
len() 可以用于字符串、列表、字典和元组——这是因为它们都实现了 __len__。这就是内置多态。
for obj in ['hello', [1,2,3], {'a':1}]:
print(type(obj).__name__, len(obj))运算符重载
+ 可以用于整数、浮点数、字符串和列表,因为每种类型都以不同方式实现了 __add__。
print(1 + 2) # int addition
print('a' + 'b') # string concat
print([1] + [2]) # list concat基于协议的鸭子类型
迭代协议规定:任何拥有 __iter__ 和 __next__ 的对象都可以用于 for 循环——无需继承基类。
class Squares:
def __init__(self, n): self.n,self.i=n,0
def __iter__(self): return self
def __next__(self):
if self.i>=self.n: raise StopIteration
x=self.i**2; self.i+=1; return x
print(list(Squares(5)))EAFP 与 LBYL
EAFP(请求宽恕比请求许可更容易)使用 try/except。LBYL(先观察再行动)使用 if/hasattr。Python 更倾向于 EAFP。
# LBYL:
if hasattr(obj, 'quack'):
obj.quack()
# EAFP (Pythonic):
try:
'hello'.quack()
except AttributeError:
print('no quack')使用 isinstance() 安全分派
当您需要针对不同类型执行特定行为时,使用 isinstance() 比捕获 AttributeError 更清晰。
def process(data):
if isinstance(data, str):
return data.upper()
elif isinstance(data, list):
return [x*2 for x in data]
print(process('hi'))
print(process([1,2,3]))将抽象基类用作协议
from abc import ABC, abstractmethod 定义了正式协议。子类必须实现抽象方法。
from abc import ABC, abstractmethod
class Drawable(ABC):
@abstractmethod
def draw(self): pass
class Circle(Drawable):
def draw(self): print('O')
Circle().draw()typing.Protocol(3.8+)
class MyProtocol(Protocol): 无需使用 ABC 即可定义结构化子类型。它可以与 mypy 一起进行静态检查。
from typing import Protocol
class Quackable(Protocol):
def quack(self) -> str: ...
def make_quack(x: Quackable) -> str:
return x.quack()
print('protocol demo')实际应用中的多态
请设计能够接受任何具有正确接口的对象的 API。这样无需修改代码即可扩展其功能。
class JSONSerializer:
def serialize(self, obj): import json; return json.dumps(obj)
class XMLSerializer:
def serialize(self, obj): return f'<data>{obj}</data>'
def export(data, serializer):
return serializer.serialize(data)
print(export({'x': 1}, JSONSerializer()))快速检查
在 Python 中,鸭子类型是什么意思?
回顾
多态:相同接口,不同行为。鸭子类型:关注行为,而不是类型。协议以非正式方式定义接口。EAFP(try/except)符合 Python 风格。
继续学习
进步非常出色!请继续学习,掌握下一个概念。
免费开始
用 AI 导师学习 Python — 免费
在浏览器中编写并运行真实代码,获得全天候 AI 导师的即时帮助,并在网页或应用中继续学习。
- 课程
- 76
- 课程
- 320
常见问题解答
「多态与鸭子类型」课时是免费的吗?
是的 — 「多态与鸭子类型」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Python Academy 课程的其余内容,请升级到 CoddyKit PRO。 Python Academy 课程共包含 4 节课。
「多态与鸭子类型」这节课中我会学到什么?
编写适用于任何兼容对象的多态代码。 你通过在浏览器中直接运行的动手代码来练习 Python Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 Python Academy 需要有经验吗?
无需任何先前经验。CoddyKit 上的 Python Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 4 节课,共 4 节。
「多态与鸭子类型」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 Python Academy 课中编写并运行代码吗?
能。每节 Python Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。
此课程中的所有课时
- 单继承
- 方法重写与 super()
- 多重继承与 MRO
- 多态与鸭子类型