当值是 cls 的实例时,您可以注释返回类型吗?
给定一个带有用于初始化的辅助方法的类:
Given a class with a helper method for initialization:
class TrivialClass:
def __init__(self, str_arg: str):
self.string_attribute = str_arg
@classmethod
def from_int(cls, int_arg: int) -> ?:
str_arg = str(int_arg)
return cls(str_arg)
是否可以注释from_int
方法的返回类型?
Is it possible to annotate the return type of the from_int
method?
我尝试了 cls
和 TrivialClass
但 PyCharm 将它们标记为未解析的引用,这在当时听起来很合理.
I'v tried both cls
and TrivialClass
but PyCharm flags them as unresolved references which sounds reasonable at that point in time.
使用泛型来表示你将返回一个 cls
的实例:>
Use a generic type to indicate that you'll be returning an instance of cls
:
from typing import Type, TypeVar
T = TypeVar('T', bound='TrivialClass')
class TrivialClass:
# ...
@classmethod
def from_int(cls: Type[T], int_arg: int) -> T:
# ...
return cls(...)
任何覆盖类方法但随后返回父类(TrivialClass
或仍然是祖先的子类)的实例的子类都将被检测为错误,因为工厂方法被定义为返回 cls
类型的实例.
Any subclass overriding the class method but then returning an instance of a parent class (TrivialClass
or a subclass that is still an ancestor) would be detected as an error, because the factory method is defined as returning an instance of the type of cls
.
bound
参数指定 T
必须是 TrivialClass
的(子类);因为在定义泛型时该类尚不存在,所以您需要使用 forward 引用(带有名称的字符串).
The bound
argument specifies that T
has to be a (subclass of) TrivialClass
; because the class doesn't yet exist when you define the generic, you need to use a forward reference (a string with the name).
注意:此答案的第一次修订提倡使用前向引用将类本身命名为返回值,但 issue 1212 使得使用泛型成为可能,更好的解决方案.
Note: The first revision of this answer advocated using a forward reference naming the class itself as the return value, but issue 1212 made it possible to use generics instead, a better solution.
从 Python 3.7 开始,当您使用 from __future__ import annotations
,但是创建了一个TypeVar()
模块级别的对象不是注释.即使在 Python 3.10 中也是如此,它推迟了注释中的所有类型提示解析.
As of Python 3.7, you can avoid having to use forward references in annotations when you start your module with from __future__ import annotations
, but creating a TypeVar()
object at module level is not an annotation. This is still true even in Python 3.10, which defers all type hint resolution in annotations.