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

时间:2016-08-29 11:44:26

标签: python pycharm type-hinting

给定一个带有辅助方法进行初始化的类:

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将它们标记为未解析的引用,这在当时听起来很合理。

3 个答案:

答案 0 :(得分:26)

使用泛型类型表示您将返回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或仍为祖先的子类的实例)将被检测为错误,因为工厂method被定义为返回cls

类型的实例

bound参数指定T必须是({1}}的(子类);因为在定义泛型时该类尚不存在,所以需要使用forward reference(带有名称的字符串)。

参见PEP 484的Annotating instance and class methods section

注意:此答案的第一个修订主张使用前向引用  将类本身命名为返回值,但issue 1212使得使用泛型成为可能,这是一种更好的解决方案。

答案 1 :(得分:6)

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

# 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的错误:

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

答案 2 :(得分:1)

在Python 3.7中,您可以使用__future__.annotations

from __future__ import annotations


class TrivialClass:
    # ...

    @classmethod
    def from_int(cls, int_arg: int) -> TrivialClass:
        # ...
        return cls(...)

编辑:您不能在不覆盖类方法的情况下继承TrivialClass的子类,但是如果您不需要此方法,那么我认为它比前向参考更为整洁。