python-3.x - Mypy Optional dict 错误,预期类型不是可选的
问题描述
我有一个__init__
能够从三个不同路径构建正确对象的函数。由于某些参数可以重复使用,因此它们在顶级 init 中具有默认值。
我不确定如何告诉 mypy 给定的参数在顶级 init 函数中是可选的,并且对于给定的正确路径是必需的。
common_record.py:138: error: Argument 1 to "_init_from_common_record" of "CommonRecord" has incompatible type "Optional[Dict[Any, Any]]"; expected "Dict[Any, Any]"
common_record.py:142: error: Argument 1 to "_init_from_raw_data" of "CommonRecord" has incompatible type "Optional[Dict[Any, Any]]"; expected "Dict[Any, Any]"
Makefile:74: recipe for target 'type-check' failed
make: *** [type-check] Error 1
class CommonRecord:
"""A Common Record type. This is a json serializable object that contains
sections for required and known fields that are common among data sources.
"""
def __init__(
self,
record: Dict = None,
raw_record: Dict = None,
*,
system: System = None,
domain: Domain = None) -> None:
"""Initialization for the Common Record Class
Three valid creation cases:
* A single dictionary indicating a dictionary that's of the Common
Record type
* A normalized record and a raw record that will be turned into a
Common Record.
* A System object, a Domain object, and a raw record dictionary.
"""
if not raw_record:
self._init_from_common_record(record)
elif (system and domain and raw_record):
self._init_from_objects(system, domain, raw_record)
else:
self._init_from_raw_data(record, raw_record)
初始化函数的签名是
def _init_from_raw_data(self, record: Dict, raw_record: Dict) -> None:
def _init_from_objects(
self,
system: System,
domain: Domain,
raw_record: Dict) -> None:
def _init_from_common_record(self, common_record: Dict) -> None:
解决方案
您可以采取三种不同的方法。
首先,您可以修改条件以明确检查 if record
is None 并执行以下操作。
if not raw_record and not record:
self._init_from_common_record(record)
elif (system and domain and raw_record):
self._init_from_objects(system, domain, raw_record)
elif not record:
self._init_from_raw_data(record, raw_record)
else:
# Raise an exception here or something
其次,您可以添加检查以确保record
不是无的断言。
if not raw_record:
assert record is not None
self._init_from_common_record(record)
elif (system and domain and raw_record):
self._init_from_objects(system, domain, raw_record)
else:
assert record is not None
self._init_from_raw_data(record, raw_record)
第三种解决方案是转换record
为正确的类型并完全跳过检查。不过我不推荐这种方法——验证你的对象是否被正确使用将是更强大的事情。
您还可以进行的一项额外但有些不相关的改进是使用重载改进构造函数的签名——基本上为每个构造 CommonRecord 的方法创建一个重载。这将有助于验证您是否始终正确地构造对象并“教”mypy 如何验证我们在上面在类型检查时所做的一些运行时检查。
但是,如果您希望您的实际实现正确进行类型检查,您仍然需要执行上面建议的三种方法之一。
您还可以做的另一件事是通过将两个私有初始化方法转换为静态方法来完全回避这个问题,这些方法将构造并返回一个新的CommonRecord
.
这将使您有可能简化构造函数并帮助您使类型更精确。当然,主要的缺点是实例化一个新的 CommonRecord 现在变得稍微笨重了。
推荐阅读
- python - 如何使用 Poetry 将 Python 包部署到 Gitlab 包注册表?
- python-3.x - 没有空格的Python粘贴图像Alpha通道
- vue.js - 带有内置过滤器的下拉菜单不会在 Vuejs 中设置 v-model 值
- html - 为什么手机底部有多余的空间?
- kubernetes - 如何通过 Google Cloud Classic VPN 从外部网络连接到 Kubernetes 工作负载集群 IP?
- javascript - 通过保留 URL 加载 Firebase SDK 会出现“权限被拒绝”错误
- angular - Angular 8 和 Okta 注销不起作用,因为用户在应用程序内被重定向
- heroku - 检测 rails 配置失败将 HEROKU_DEBUG_RAILS_RUNNER=1 设置为调试
- python - Python:如何找到最频繁的元素组合?
- pointers - 将指针分配给 NativeInt 会导致 E2010 不兼容的类型