问题
我想声明一个实例属性,类型提示为float
,而不在初始化时分配值。该值是在实例初始化后(也称为__init__
之后)在运行时分配的。
根据this answer,我可以将值设置为None
。但是,我的IDE(PyCharm
)产生一个PyTypeChecker
标志,说Expected type 'float', got type 'None' instead
。
我发现是否将值设置为省略号(由this answer表示),又名value = ...
,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中是什么样子
版本信息
2019.2.5
3.6
答案 0 :(得分:1)
在简单的情况下,您实际上可以不用在构造函数中执行任何操作:如果执行此操作,则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 None
,self._unassigned_val is None
或isinstance(self._unassigned_val, float)
的组合进行检查,并断言使类型检查器有条件地缩小字段的类型。
这最后一种方法是我本人的工作:我非常喜欢类型检查器,并设置我的工具以非常主动地检测潜在问题。
关于省略号的最后一条注解:仅在存根以及使用Protocols方法定义或abstract classes之类的东西时,才将省略号用作占位符-基本上,在您从未真正结束的情况下使用字段的值/方法参数/在运行时进行的任何操作。