Menu
CoddyTech

鸭子类型

本课属于 Coddy Python 学习旅程的“面向对象编程”单元。第 24 课,共 64 课。

鸭子类型关注对象能做什么,而不是它是什么。只要对象具有你需要的方法,你就可以使用它,无论它属于什么类。

下面是两个互不相关但具有相同方法的类:

class Duck:
    def swim(self):
        return "Duck swimming"
    
    def quack(self):
        return "Quack!"

class Person:
    def swim(self):
        return "Person swimming"
    
    def quack(self):
        return "Person imitating a duck: Quack!"

注意,Duck 和 Person 并没有继承自同一个父类,但它们都有 swim() 和 quack() 方法。

创建一个适用于任何“像鸭子的”对象的函数:

def make_it_swim_and_quack(duck_like_object):
    print(duck_like_object.swim())
    print(duck_like_object.quack())

这个函数不关心对象的类型,只关心对象是否有必需的方法。

对这两个类都使用该函数:

make_it_swim_and_quack(Duck())
make_it_swim_and_quack(Person())

输出:

Duck swimming
Quack!
Person swimming
Person imitating a duck: Quack!

再添加一个“像鸭子一样”的类:

class Robot:
    def swim(self):
        return "Robot swimming with propellers"
    
    def quack(self):
        return "Robot sound: BEEP BEEP!"

make_it_swim_and_quack(Robot())

输出:

Robot swimming with propellers
Robot sound: BEEP BEEP!

要点:鸭子类型无需继承即可实现多态。只要对象具有你需要的方法,就可以使用它。这让 Python 代码更加灵活,也遵循“请求宽恕比请求许可更容易”的原则。

challenge icon

挑战

中等

在这个挑战中,你将实现一个系统,通过不同的类文件对象演示鸭子类型:

  • textfile.py:实现 TextFile 类,包含 read() 和 write(data) 方法
  • database.py:实现 Database 类,并使用匹配的方法签名
  • networkresource.py:实现 NetworkResource 类,并使用匹配的方法签名
  • driver.py:实现测试用例,验证你的实现能否正常工作

每个文件都包含详细的 TODO 注释,指导你完成实现。

亲手试试

# TODO: 从 textfile.py 导入 TextFile 类
# TODO: 从 database.py 导入 Database 类
# TODO: 从 networkresource.py 导入 NetworkResource 类

def process_data(data_source, data):
    # TODO: 调用 data_source 的 read() 方法并打印结果
    # TODO: 调用 data_source 的 write(data) 方法并打印结果
    pass


# 使用不同的数据源进行测试。不要修改这段测试代码
text_file = TextFile()
database = Database()
network = NetworkResource()

print("Processing text file:")
process_data(text_file, "Hello, world!")

print("\
Processing database:")
process_data(database, "User record")

print("\
Processing network resource:")
process_data(network, "GET request")
quiz icon自我测试

这节课包含一个小测验。开始学习即可作答,并记录你的进度。

面向对象编程中的所有课

自己练习: Python 在线编译器