如何在运行时向 Python 类动态添加方法,同时保留其类型注释?

问题描述 投票:0回答:1
from typing import Callable

class MyClass:
    pass

def dynamic_method(self, x: int, y: str) -> str:
    return f"{x} - {y}"

setattr(MyClass, 'dynamic_method', dynamic_method)


instance = MyClass()
print(instance.dynamic_method(42, "hello"))  # This works


from inspect import signature
print(signature(MyClass.dynamic_method))

动态添加的方法在调用时按预期工作,但类型注释未与该方法正确关联。当我检查方法签名时,它没有显示我在dynamic_method中定义的注释。

python methods
1个回答
0
投票

发生这种行为是因为 setattr 直接将函数作为属性添加到类中,但没有将其完全绑定为具有预期类型注释和元数据的正确方法。在此设置中,inspect.signature 函数无法正确检测类型注释,因为dynamic_method 最初并未定义为类中的方法。

为了确保动态添加的方法保留其类型注释,您可以使用 FunctionType 并显式设置 annotations 属性或使用 types.MethodType 正确绑定函数。以下是解决此问题的方法:

使用FunctionType的解决方案 蟒蛇

from types import FunctionType
from inspect import signature

class MyClass:
    pass

def dynamic_method(self, x: int, y: str) -> str:
    return f"{x} - {y}"

# Ensure the function is properly bound and retains annotations
dynamic_method_with_annotations = FunctionType(
    dynamic_method.__code__,
    dynamic_method.__globals__,
    dynamic_method.__name__,
    dynamic_method.__defaults__,
    dynamic_method.__closure__
)
dynamic_method_with_annotations.__annotations__ = 
dynamic_method.__annotations__

setattr(MyClass, 'dynamic_method', dynamic_method_with_annotations)

instance = MyClass()
print(instance.dynamic_method(42, "hello"))  # This works
print(signature(MyClass.dynamic_method))  # This now shows annotations
© www.soinside.com 2019 - 2024. All rights reserved.