了解接口类型duck typing

举报
码乐 发表于 2025/11/26 09:05:12 2025/11/26
【摘要】 1 简介本文简介duck typing类型, 一个简洁、可直接运行的 Python3 示例,展示“鸭子类型”(duck typing) 如何让代码灵活 + 简洁;最后说明 Flask 与 Django 中有哪些典型地方使用了这一思想。 2 Python 鸭子类型示例无需关心对象的真实类型,这就是鸭子类型核心思想: “If it walks like a duck and quacks ...

1 简介

本文简介duck typing类型, 一个简洁、可直接运行的 Python3 示例,展示“鸭子类型”(duck typing) 如何让代码灵活 + 简洁;最后说明 Flask 与 Django 中有哪些典型地方使用了这一思想。

2 Python 鸭子类型示例

无需关心对象的真实类型,这就是鸭子类型核心思想:

			“If it walks like a duck and quacks like a duck, it's a duck.”

只要对象实现了所需的行为(方法/属性),就可以被当作某类对象使用,不关心其实际类型或继承体系。

  • 示例 1:

同一函数可以处理不同类型的对象

        class FileLike:
            def read(self):
                return "I behave like a file"


        class NetworkStream:
            def read(self):
                return "I behave like a network stream"


        def process(stream):
            # 不关心 stream 是否是 file stream / network stream / memory buffer
            print("Reading:", stream.read())

不同对象,只要有 read() 方法,就都能用

    process(FileLike())
    process(NetworkStream())
  • 优点

无需定义共同接口(无须 Java 式接口/继承)

函数只要求“对象能干什么”,而非“对象是什么类型”

  • 示例 2:

支持 len() 的对象不必继承任何类

    class MyCollection:
        def __init__(self, items):
            self.items = items

        def __len__(self):
            return len(self.items)

调用实例

    c = MyCollection([1,2,3])
    print(len(c))

len() 不要求继承,它只需要对象实现 len
这就是 Python 的“结构化行为接口”。

3、Flask 中的鸭子类型典型应用

Flask 是一个非常典型、充分利用鸭子类型的框架:

    1. WSGI request/response 对象可插拔

Flask 的视图函数既可以返回:

      字符串

      字典

      tuple

      Response 对象
			等

Flask 内部通过 duck typing 把返回值自动转换成 Response:

    @app.route("/")
    def index():
        return {"msg": "Hello"}   # Flask 会自动 jsonify

Flask 内部逻辑类似:

    def make_response(rv):
        if isinstance(rv, Response):
            return rv
        elif isinstance(rv, dict):
            return jsonify(rv)
        elif isinstance(rv, str):
            return Response(rv)

你只返回“能像响应一样用”的内容就行。

    1. request 对象可使用 file-like object

上传文件获得的是 FileStorage,它实现了 .read(),可像文件一样使用:

  f = request.files["file"]
  content = f.read()  # 像文件一样

你无需关心它不是 open() 打开的文件。
这是典型 duck typing。

4、Django 中的duck typing类型典型应用

虽然 Django 更“重量级”,但同样大量使用 duck typing:

    1. 中间件(Middleware)链不要求特定类型

只要对象实现 call(request),即可作为中间件。

    class MyMiddleware:
        def __init__(self, get_response):
            self.get_response = get_response

        def __call__(self, request):
            # request 可以是任何拥有必要属性的对象
            return self.get_response(request)

Django 不要求中间件继承某个基类。

    1. Django ORM 的 QuerySet 支持迭代协议

你可以像列表一样遍历 QuerySet:

    for user in User.objects.all():
        print(user)

因为 QuerySet 实现了 iter —— 不需要继承 list。

    1. 文件存储后端:只要求类似文件的行为

Django Storage backend 只要求对象提供:

    .open()

    .save()

    .read()

    .write()

你可以实现自己的存储:

    class MyStorage:
        def save(self, name, content):
            # content 只要有 read() 方法即可
            data = content.read()

完全基于行为判断,不需继承。

5 小结

Python、Flask、Django 都依赖鸭子类型,通过“看行为不看类型”实现了灵活、简洁、可插拔的设计。

  框架  使用duck typing类型的地方   好处
  Flask   Response 接受多种返回值 / 上传文件像文件对象 / request 对象可替换    极度灵活、易扩展
  Django  Middleware、QuerySet、Storage Backend 插件式的可插拔设计,更可维护
【版权声明】本文为华为云社区用户原创内容,未经允许不得转载,如需转载请自行联系原作者进行授权。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。