全部学科
Python全栈
python
NodeJS全栈
nodejs
小程序首页
📅 2026-05-19 8 分钟 ✍️ juanwangdev

Python 多态与动态绑定

Python 多态基于鸭子类型,不依赖继承关系,只需对象具备所需方法。

鸭子类型

"如果它走起来像鸭子,叫起来像鸭子,那它就是鸭子。"

Python
class Duck:
    def swim(self):
        print("鸭子游泳")

    def quack(self):
        print("嘎嘎")


class Person:
    def swim(self):
        print("人游泳")

    def quack(self):
        print("人模仿鸭子叫")


class Robot:
    def swim(self):
        print("机器人游泳")

    def quack(self):
        print("电子嘎嘎")


def make_it_quack(thing):
    "不关心类型,只要有 quack 方法"
    thing.quack()


def make_it_swim(thing):
    "不关心类型,只要有 swim 方法"
    thing.swim()


# 任何有这些方法的对象都可以使用
make_it_quack(Duck())    # 嘎嘎
make_it_quack(Person())  # 人模仿鸭子叫
make_it_quack(Robot())   # 电子嘎嘎

make_it_swim(Duck())     # 鸭子游泳
make_it_swim(Person())   # 人游泳

多态示例

Python
class File:
    def read(self):
        return "文件内容"


class Network:
    def read(self):
        return "网络数据"


class Database:
    def read(self):
        return "数据库记录"


def process_data(source):
    "多态:任何有 read 方法的对象都适用"
    data = source.read()
    return f"处理: {data}"


print(process_data(File()))      # 处理: 文件内容
print(process_data(Network()))   # 处理: 网络数据
print(process_data(Database()))  # 处理: 数据库记录

继承多态

Python
class Animal:
    def speak(self):
        pass


class Dog(Animal):
    def speak(self):
        return "汪汪"


class Cat(Animal):
    def speak(self):
        return "喵喵"


class Cow(Animal):
    def speak(self):
        return "哞哞"


def animal_sound(animal: Animal):
    "基于继承的多态"
    print(animal.speak())


animals = [Dog(), Cat(), Cow()]
for animal in animals:
    animal_sound(animal)
# 汪汪
# 喵喵
# 哞哞

动态绑定

方法在运行时绑定到对象:

Python
class A:
    def method(self):
        print("A 方法")


class B:
    def method(self):
        print("B 方法")


def call_method(obj):
    obj.method()  # 运行时动态绑定


call_method(A())  # A 方法
call_method(B())  # B 方法

# 同一变量可以是不同类型
obj = A()
obj.method()  # A 方法
obj = B()
obj.method()  # B 方法

方法动态添加

Python
class Dynamic:
    pass


def new_method(self):
    print("动态添加的方法")


d = Dynamic()

# 运行时添加方法
import types
d.method = types.MethodType(new_method, d)
d.method()  # 动态添加的方法

# 添加到类
Dynamic.class_method = new_method
Dynamic().class_method()  # 动态添加的方法

getattr 实现动态方法

Python
class DynamicProxy:
    def __getattr__(self, name):
        "动态创建方法"
        def method(*args, **kwargs):
            print(f"调用 {name},参数: {args}, {kwargs}")
            return f"结果: {name}"
        return method


proxy = DynamicProxy()
print(proxy.any_method(1, 2, key="value"))
# 调用 any_method,参数: (1, 2), {'key': 'value'}
# 结果: any_method

多态与类型检查

Python
# 鸭子类型:不检查类型
def process_duck(obj):
    obj.quack()  # 只要有 quack 方法


# 类型检查:检查是否是特定类型
def process_with_check(obj):
    if hasattr(obj, 'quack'):
        obj.quack()
    else:
        print("对象没有 quack 方法")


# 抽象基类:强制接口
from abc import ABC, abstractmethod


class Quacker(ABC):
    @abstractmethod
    def quack(self):
        pass


def process_with_abc(obj: Quacker):
    obj.quack()  # 类型检查确保有 quack 方法

协议与抽象基类

Python
from collections.abc import Sized, Iterable


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

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

    def __iter__(self):
        return iter(self.data)


# 自动符合协议(鸭子类型)
mc = MyCollection([1, 2, 3])
print(isinstance(mc, Sized))      # True(有 __len__)
print(isinstance(mc, Iterable))   # True(有 __iter__)

# 无需显式继承
def get_size(obj: Sized):
    return len(obj)


def iterate(obj: Iterable):
    return list(obj)


print(get_size(mc))    # 3
print(iterate(mc))     # [1, 2, 3]

运算符多态

Python
class Point:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def __add__(self, other):
        return Point(self.x + other.x, self.y + other.y)

    def __str__(self):
        return f"({self.x}, {self.y})"


p1 = Point(1, 2)
p2 = Point(3, 4)

print(p1 + p2)  # (4, 6)(+ 运算符多态)

函数多态

内置函数对不同类型有不同行为:

Python
# len() 多态
print(len([1, 2, 3]))      # 3(列表长度)
print(len("hello"))        # 5(字符串长度)
print(len({"a": 1}))       # 1(字典长度)
print(len(range(10)))      # 10(range长度)

# str() 多态
print(str(123))            # 123(整数)
print(str([1, 2]))         # [1, 2](列表)
print(str({"a": 1}))       # {'a': 1}(字典)

# sorted() 多态
print(sorted([3, 1, 2]))   # [1, 2, 3]
print(sorted("hello"))     # ['e', 'h', 'l', 'l', 'o']
print(sorted({"a": 1, "b": 2}))  # ['a', 'b'](按键排序)

接口协议示例

Python
class Reader:
    "读取接口"

    def read(self):
        raise NotImplementedError


class Writer:
    "写入接口"

    def write(self, data):
        raise NotImplementedError


class FileReader(Reader, Writer):
    def __init__(self, filename):
        self.filename = filename

    def read(self):
        with open(self.filename, 'r') as f:
            return f.read()

    def write(self, data):
        with open(self.filename, 'w') as f:
            f.write(data)


class NetworkReader(Reader):
    def read(self):
        return "网络数据"


class ConsoleWriter(Writer):
    def write(self, data):
        print(data)


# 多态使用
def copy_data(reader, writer):
    data = reader.read()
    writer.write(data)


copy_data(FileReader("source.txt"), ConsoleWriter())
copy_data(NetworkReader(), FileReader("dest.txt"))

鸭子类型 vs 显式接口

方式特点
鸡子类型无需继承,灵活,无编译检查
抽象基类强制接口,有类型检查保障
类型注解提供静态提示,不强制运行
Python
# 鸡子类型
def process(obj):
    obj.method()  # 运行时可能失败


# 抽象基类
def process(obj: Interface):
    obj.method()  # 确保有 method

动态属性绑定

Python
class Dynamic:
    pass


d = Dynamic()

# 运行时添加属性
d.name = "动态"
d.value = 100

print(d.name)   # 动态
print(d.value)  # 100

# 动态删除属性
del d.value
# print(d.value)  # AttributeError

要点总结

要点说明
鸡子类型只需具备方法,无需继承
多态同一接口不同实现
动态绑定运行时确定方法调用
协议通过方法集合定义接口
hasattr()检查对象是否有方法

Python 多态基于鸭子类型,灵活但无编译时检查;抽象基类提供接口约束保障。

D:\git2\jwdev\articles\PYTHON\进阶\面向对象编程\多态与动态绑定.md

📝 发现内容有误?点击此处直接编辑

← 上一篇 Python异常类型
下一篇 → Python 属性访问控制
想查看更多题目和详细解析?
小程序提供完整的题库、模拟考试和详细解析
马上就来

长按或扫描二维码,立即体验

扫码体验小程序
马上就来
使用微信扫描二维码
立即体验完整题库