我正在接收来自远程方的消息,这些消息被解码为如下所示的类:
class SomeMessage(MessageType):
foo: Optional[int]
bar: Optional[str]
quux: Optional[AnotherMessageType]
大多数字段始终是可选的。有线消息可能包含也可能不包含。
但是,我的代码事先进行了验证,然后大多假定存在适当的字段。
例如:
def process_all_foos(messages: List[SomeMessage]):
messages_with_foo = [m for m in messages if m.foo is not None]
foo_sum = sum(m.foo for m in messages_with_foo)
该代码无法进行类型检查,因为mypy不会保留先前的检查。
是否有可能进行上述代码的类型检查以某种方式>>而不会产生运行时成本?
我的想法是创建一个具有更高要求的协议:
class SomeMessageWithFoo(Protocol): foo: int def convert_foo(m: SomeMessage) -> SomeMessageWithFoo: assert m.foo is not None return m # or, ideally: def process_all_foos(messages: List[SomeMessage]): messages_with_foo: List[SomeMessageWithFoo] = [m for m in messages if m.foo is not None] foo_sum = sum(m.foo for m in messages_with_foo)
但是,mypy拒绝了:
检查该字段。test.py:16: error: Incompatible return value type (got "SomeMessage", expected "SomeMessageWithFoo") [return-value] test.py:16: note: Following member(s) of "SomeMessage" have conflicts: test.py:16: note: foo: expected "int", got "Optional[int]" test.py:20: error: List comprehension has incompatible type List[SomeMessage]; expected List[SomeMessageWithFoo] [misc] test.py:20: note: Following member(s) of "SomeMessage" have conflicts: test.py:20: note: foo: expected "int", got "Optional[int]"
我考虑使用
cast(SomeMessageWithFoo, m)
,或更可能使用# type: ignore
,因为这没有运行时成本。 (我在嵌入式环境中,因此我确实关心cast
的函数调用。)但这也让我not
即,以下错误地进行类型检查:
def convert_foo(m: SomeMessage) -> SomeMessageWithFoo: # someone commented this out: #assert m.foo is not None return cast(SomeMessageWithFoo, m)
是否有一种方法可以完成此过程,从而进行代码类型检查,但实际上仍可以验证需求?
我正在接收来自远程方的消息,这些消息被解码成如下所示的类:class SomeMessage(MessageType):foo:可选[int]栏:可选[str]队列:可选[...
我不明白。显而易见的解决方案不是a)使您的代码更快,因为您只执行一次迭代而不是两次,并且b)修复了类型检查: