关于python:当值是cls的实例时,你能注释返回类型吗?

Can you annotate return type when value is instance of cls?

给定一个具有用于初始化的帮助器方法的类:

1
2
3
4
5
6
7
8
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方法的返回类型?

我试过clsTrivialClass,但pycharm将它们标记为未解决的参考,这在当时听起来是合理的。


使用泛型类型指示将返回cls的实例:

1
2
3
4
5
6
7
8
9
10
11
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类型的实例。

bound参数指定T必须是TrivialClass的(子类);因为在定义泛型时类还不存在,所以需要使用前向引用(具有名称的字符串)。

请参见PEP484的注释实例和类方法部分。

注:该答案的第一次修订建议使用前向参考。将类本身命名为返回值,但问题1212使使用泛型成为可能,这是一个更好的解决方案。


注释返回类型的一种简单方法是使用字符串作为类方法返回值的注释:

1
2
3
4
5
6
7
8
9
# test.py
class TrivialClass:
  def __init__(self, str_arg: str) -> None:
    self.string_attribute = str_arg

  @classmethod
  def from_int(cls, int_arg: int) -> 'TrivialClass':
    str_arg = str(int_arg)
    return cls(str_arg)

这将传递mypy 0.560,而python没有错误:

1
2
$ mypy test.py --disallow-untyped-defs --disallow-untyped-calls
$ python test.py