我有一个__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)
具有init函数的签名
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:
答案 0 :(得分:1)
您可以采用三种不同的方法。
首先,您可以修改条件以显式检查record
是否为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
强制转换为正确的类型,并完全跳过检查。不过,我不推荐这种方法-验证对象是否正确使用将是更可靠的选择。
您还可以进行的另一项但又不相关的改进是使用overloads完善构造函数的签名-基本上,每种构造CommonRecord的方法都会产生一个重载。这将有助于验证您始终在正确构造对象,并“教” mypy如何在类型检查时验证我们上面所做的一些运行时检查。
但是,如果您希望您的实际实现正确地进行类型检查,则仍然需要执行上面建议的三种方法之一。
您可以做的另一件事是,通过将两个私有初始化方法转换为静态方法来完全解决问题,该方法将构造并返回CommonRecord
的新实例。
这将使您潜在地简化构造函数并帮助您使类型更精确。当然,主要的缺点是现在实例化一个新的CommonRecord变得有些笨拙。