python - Python 使用省略号或无 + 浮点类型提示未分配属性
问题描述
问题
我想声明一个实例属性,类型提示为 a float
,而不在初始化时分配值。该值是在运行时分配的,在实例初始化之后(也称为 after __init__
)。
根据这个答案,我可以将值设置为None
。但是,我的 IDE ( PyCharm
) 提出了一个PyTypeChecker
标志,说Expected type 'float', got type 'None' instead
.
我发现如果我将值设置为省略号(由这个答案建议),也就是 value = ...
,PyCharm 不再抱怨。
这里的最佳做法是什么? 我应该使用None
or...
吗?
示例代码
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 中的样子:
版本信息
- PyCharm 社区版
2019.2.5
- Python
3.6
解决方案
对于简单的情况,您实际上可以在构造函数中不做任何事情:如果您这样做,mypy 和 Pycharm 都将继续正确推断您的字段类型:
class SomeClass:
def called_during_runtime(self) -> None:
self._unassigned_val = 1.0
当然,您需要承担确保在运行时实际调用此函数的责任:如果您这样做,您的类型检查器不会警告您。
如果您的函数以足够复杂的方式为该字段分配值,您的类型检查器可能会窒息并且不知道该怎么做。在这种情况下,如果您使用的是 Python 3.6 或更高版本,则可以使用变量注释:
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
而且,如果您改变主意并决定偏向类型检查器,并对其警告更具侵略性,则始终可以声明您的值可以是浮点数或无:
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)
最后一种方法是我个人所做的:我是类型检查器的粉丝,并且将我的工具设置为非常积极地检测潜在问题。
关于省略号的最后一点注意事项:使用省略号作为占位符仅适用于存根以及使用诸如协议方法定义或抽象类之类的东西时- 基本上,在您从未最终实际使用字段/方法参数的值的情况下/无论在运行时。
推荐阅读
- javascript - 如何检测 Node.js 中是否存在 HTTP 代理?
- uwp - 我可以在不使用 Add-AppDevPackage.ps1 的情况下构建安装时完全依赖的 UWP 侧载应用吗?
- r - 如何总结 R 中的字符、因子和数值向量
- javascript - 如何设置对变量的承诺响应
- reactjs - react-redux 道具未更新
- javascript - Vuejs2 监听页面滚动失败
- scala - 如何在 AWS Glue 在 Spark 中创建的 Dataframe 上运行 SQL SELECT?
- codeigniter - 如何在一列中获取所有数据?
- java - 如何实现联合查找算法?
- javascript - 我的浏览器没有执行我的 Javascript 代码。浏览器只是按照在我的文本编辑器上编写的方式输出它