gpt4 book ai didi

python - 当包装器具有实例变量时键入类装饰器

转载 作者:行者123 更新时间:2023-11-28 18:02:37 25 4
gpt4 key购买 nike

考虑到 mypy 的当前限制,这个装饰器的类型是否正确?我在下面包含示例用法:

import functools
from typing import TypeVar, Type, Any, cast

C = TypeVar('C', bound=Type[Any])


def singleton(cls: C) -> C:
"""Transforms a class into a Singleton (only one instance can exist)."""

@functools.wraps(cls)
def wrapper(*args: Any, **kwargs: Any) -> Any:
if not wrapper.instance: # type: ignore # https://github.com/python/mypy/issues/2087
wrapper.instance = cls(*args, **kwargs) # type: ignore # https://github.com/python/mypy/issues/2087
return wrapper.instance # type: ignore # https://github.com/python/mypy/issues/2087

wrapper.instance = None # type: ignore # https://github.com/python/mypy/issues/2087
return cast(C, wrapper)


@singleton
class Test:
pass


if __name__ == '__main__':
a = Test()
b = Test()
print(a is b)

我必须在 instance 属性出现的行上添加 type: ignore,否则 mypy 会标记这些错误:

错误:“Callable[..., Any]”没有属性“instance”

最佳答案

您的函数接受类型为 C 的参数并返回相同类型的结果。因此,根据 mypy ab 将具有相同的类型。您可以使用 reveal_type 检查它。

reveal_type(a) # Revealed type is 'test.Test'
reveal_type(b) # Revealed type is 'test.Test'

无论如何,cast# type: ignore 都应该谨慎使用,因为它们告诉 mypy 相信您(开发人员)类型是正确的,即使它无法确认。

我在您的代码中看到的潜在问题是您正在用一个函数替换一个类(即 Test),这可能会破坏一些代码。例如:

>>> Test
<function Test at 0x7f257dd2bae8>
>>> Test.mro()
AttributeError: 'function' object has no attribute 'mro'

您可以尝试的另一种方法是替换装饰类的 __new__ 方法:

def singleton(cls: C) -> C:
"""Transforms a class into a Singleton (only one instance can exist)."""

new = cls.__new__

def _singleton_new(cls, *args, **kwds):
try:
inst = cls._instance
except AttributeError:
cls._instance = inst = new(cls, *args, **kwds)
return inst

cls.__new__ = _singleton_new
return cls

在这种情况下,您不会替换整个类,因此您不太可能破坏使用该类的其他代码:

>>> Test                                                                                                                                                   
test.Test

>>> Test.mro()
[test.Test, object]

请注意,上面的代码只是一个示例,用于显示您当前方法的局限性。因此,您可能不应该按原样使用它,而应该寻找更可靠的解决方案。

关于python - 当包装器具有实例变量时键入类装饰器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55082306/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com