
在这种情况下,interface.foo 和 interface.bar 会被类型检查器标记为 (variable) foo/bar: any,而不是预期的 (property) foo/bar: str。这会导致类型检查的缺失和代码提示的不准确。
为了解决这个问题,我们可以自定义一个泛型 Property 类,继承自 Python 内置的 property 类,并使用 typing 模块中的 Generic 和 TypeVar 来指定属性的类型。
from typing import Any, Generic, TypeVar, overload, cast, Callable
T = TypeVar('T') # The return type
I = TypeVar('I') # The outer instance's type
class Property(property, Generic[I, T]):
def __init__(
self,
fget: Callable[[I], T] | None = None,
fset: Callable[[I, T], None] | None = None,
fdel: Callable[[I], None] | None = None,
doc: str | None = None
) -> None:
super().__init__(fget, fset, fdel, doc)
@overload
def __get__(self, instance: None, owner: type[I] | None = None) -> Callable[[I], T]:
...
@overload
def __get__(self, instance: I, owner: type[I] | None = None) -> T:
...
def __get__(self, instance: I | None, owner: type[I] | None = None) -> Callable[[I], T] | T:
return cast(Callable[[I], T] | T, super().__get__(instance, owner))
def __set__(self, instance: I, value: T) -> None:
super().__set__(instance, value)
def __delete__(self, instance: I) -> None:
super().__delete__(instance)这个 Property 类接受两个类型变量:I 表示外部实例的类型,T 表示属性的返回类型。通过重写 __init__ 和 __get__ 方法,我们可以保留属性的类型信息。
现在,我们可以使用自定义的 Property 类来创建属性。首先,我们需要定义 getter 和 setter 函数的类型:
from collections.abc import Callable
Getter = Callable[['Interface'], str]
Setter = Callable[['Interface', str], None]
def complex_property(name: str) -> tuple[Getter, Setter]:
def _getter(self: Interface) -> str:
return name # Replace with your complex logic
def _setter(self: Interface, value: str) -> None:
pass # Replace with your complex logic
return _getter, _setter然后,我们可以将这些函数传递给 Property 类的构造函数:
class Interface:
foo = Property(*complex_property("foo"))现在,我们可以使用类型检查器来验证类型提示是否正确:
instance = Interface()
reveal_type(Interface.foo) # mypy => (Interface) -> str
# pyright => (Interface) -> str
reveal_type(instance.foo) # mypy + pyright => str
instance.foo = 42 # mypy => error: Incompatible types in assignment
# pyright => error: "Literal[42]" is incompatible with "str" ('foo' is underlined)
instance.foo = 'lorem' # mypy + pyright => fine可以看到,类型检查器现在可以正确地推断出 Interface.foo 和 instance.foo 的类型为 str,并且可以在类型不匹配时发出错误。
通过自定义泛型 Property 类,我们可以有效地解决在使用工厂方法创建类属性时类型提示丢失的问题。这种方法可以提高代码的可读性和可维护性,并减少潜在的类型错误。虽然自定义 property 类稍微增加了代码的复杂性,但它带来的类型安全性和代码提示的提升是值得的。
以上就是如何为使用工厂方法创建的类属性添加类型提示的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号