Python离开属性未使用省略号或None +类型的float提示

问题描述 投票:1回答:1

问题

我想声明一个实例属性,类型提示为float,而不在初始化时分配值。该值是在实例初始化后(也称为__init__之后)在运行时分配的。

根据this answer,我可以将值设置为None。但是,我的IDE(PyCharm)引发一个PyTypeChecker标志,说Expected type 'float', got type 'None' instead

[我发现是否将值设置为省略号(由this answer表示),又名值= ...,PyCharm不再抱怨。

这里的最佳做法是什么?应该使用None还是...


示例代码

class SomeClass:

    def __init__(self):
        """Initialize with an unassigned value."""

        # PyCharm complains here
        self._unassigned_val = None  # type: float

        # PyCharm doesn't complain here
        self._unassigned_val2 = ...  # type: float

    def called_during_runtime(self) -> None:
        """This gets called after __init__ has run."""
        self._unassigned_val = 1.0
        self._unassigned_val2 = 1.0

在我的IDE中看起来像:

Sample Code In PyCharm


版本信息

  • PyCharm社区版2019.2.5
  • Python 3.6
python pycharm type-hinting ellipsis duck-typing
1个回答
0
投票

对于简单的情况,您实际上可以不用在构造函数中执行任何操作:如果执行此操作,mypy和Pycharm都将继续正确推断字段的类型:

class SomeClass:
    def called_during_runtime(self) -> None:
        self._unassigned_val = 1.0

当然,您需要承担确保在运行时实际调用此函数的责任:如果您这样做,类型检查器将不会警告您。

如果您的函数以足够复杂的方式向该字段分配值,则类型检查器可能会阻塞并且不知道该怎么办。在这种情况下,如果您使用的是Python 3.6或更高版本,则可以使用Variable annotations

class SomeClass:
    _unassigned_val: float

    def called_during_runtime(self) -> None:
        self._unassigned_val = 1.0

这完全等同于运行时的第一种方法。

如果您需要支持旧版本的Python,您可以做的另一种技术是创建一个“伪造”的哨兵值,该值的类型为Any,即完全动态类型:

from typing import Any

BOGUS = object()  # type: Any

class SomeClass:
    def __init__(self) -> None:
        self._unassigned_val = BOGUS  # type: float

    def called_during_runtime(self) -> None:
        self._unassigned_val = 1.0

而且,如果您改变主意并决定要偏向于类型检查器以使其警告更为激进,则始终可以声明您的值可以为任一个] float或None:

from typing import Optional

class SomeClass:
    def __init__(self) -> None:
        self._unassigned_val = None  # type: Optional[float]

    def called_during_runtime(self) -> None:
        self._unassigned_val = 1.0

    def get_with_default(self, default: float) -> float:
        if self._unassigned_val is None:
            return default
        else:
            return self._unassigned_val

请注意,然后可以在if语句和断言中使用self._unassigned_val is not Noneself._unassigned_val is Noneisinstance(self._unassigned_val, float)的组合,以使类型检查器有条件地缩小字段的类型。

这是我个人的最后一种方法:我是类型检查器的狂热者,并且设置我的工具以非常主动地检测潜在的问题。

关于省略号的最后注解:仅在存根以及使用Protocols方法定义或abstract classes之类的东西时,才将省略号用作占位符-基本上,在您最终没有真正使用自己的值的情况下字段/方法参数/无论何时运行。

© www.soinside.com 2019 - 2024. All rights reserved.