Python class members type hinting

dab*_*ues 15 python pycharm python-3.x python-typing

I am using PyCharm to develop some Python app. I am trying to use as cutting-edge python as possible, so I am making use of new python features. I have a problem with type hinting.

Let's all take a look at my DataAnalyzer class:

class DataAnalyzer:

    def __init__(self, train_data: pd.DataFrame, test_data: pd.DataFrame) -> None:
        self.train_data = train_data
        self.test_data = test_data

    def analyze(self):
        pass
Run Code Online (Sandbox Code Playgroud)

Now PyCharm spams me with yellow bulbs wanting me to add type annotations to self.train_data and self.test_data. If I click this message to do so, PyCharm adds two lines at the beginning of my class:

class DataAnalyzer:
    train_data: pd.DataFrame
    test_data: pd.DataFrame

    def __init__(self, train_data: pd.DataFrame, test_data: pd.DataFrame) -> None:
        self.train_data = train_data
        self.test_data = test_data

    def analyze(self):
        pass
Run Code Online (Sandbox Code Playgroud)

I guess now it looks nicer, but AFAIK by writing those variables like this I make them static.

I thought about annotating the types like this:

class DataAnalyzer:

    def __init__(self, train_data: pd.DataFrame, test_data: pd.DataFrame) -> None:
        self.train_data: pd.DataFrame = train_data
        self.test_data: pd.DataFrame = test_data

    def analyze(self):
        pass
Run Code Online (Sandbox Code Playgroud)

Which is definitely not clear, but I am not making my class members static, when I don't want to.

I know, that by having the types annotated in the method signature, doing this one more time when I just assign those, is an overkill, but I am asking for the general rule. Should I annotate those types like PyCharm suggests me to, or should I do this inline?

小智 13

PyCharm 的建议是正确的。其实我觉得下面的代码更好:

class DataAnalyzer:
    train_data: pd.DataFrame
    test_data: pd.DataFrame

    def __init__(self, train_data, test_data):
        self.train_data = train_data
        self.test_data = test_data

    def analyze(self):
        pass
Run Code Online (Sandbox Code Playgroud)

解释:

  • 注释成员不会使其成为静态。
  • 我们不应该__init__再次注释函数中的参数。
  • -> Noneafter__init__可以省略。因为__init__从不返回值。

谢谢。

  • 您对 `-> None` 的评论与 [PEP 484](https://www.python.org/dev/peps/pep-0484/#the-meaning-of-annotations) 相矛盾:“请注意,`的返回类型__init__` 应该用 `-> None` 进行注释。原因很微妙。如果 `__init__` 假设返回注释为 `-> None`,那是否意味着一个无参数、未注释的 `__init__`方法仍然应该进行类型检查吗?我们只是说 __init__` 应该有一个返回注释,而不是留下这种歧义或引入异常;因此默认行为与其他方法相同。” (7认同)
  • 为什么不应该注释初始化参数的类型?它们与实例成员具有相同的名称,但实际上是不同的变量。 (6认同)

Alo*_*nme 5

两个选项都有效 - 查看pep 526

类型注释也可用于注释类主体和方法中的类和实例变量。特别是,无值表示法a: int允许对应该在__init__或 中初始化的实例变量进行注释__new__

MyPy文档也是类型提示一个很好的资源