【发布时间】:2020-06-16 08:19:50
【问题描述】:
假设我定义了一个协议Frobbable。此外,我还有一个有效的协议实现,以及一个缺少.frob() 方法的损坏实现:
from typing import Protocol
from abc import abstractmethod
class Frobbable(Protocol):
@abstractmethod
def frob(self) -> None:
raise NotImplementedError
def main(knob: Frobbable) -> None:
knob.frob()
class Knob:
def frob(self) -> None:
print("knob has been frobbed")
class BrokenKnob:
pass
main(Knob())
main(BrokenKnob())
使用 mypy 检查该程序会导致错误,正如预期的那样:
testprotocol.py:25:6: error: Argument 1 to "main" has incompatible type "BrokenKnob"; expected "Frobbable" [arg-type]
main(BrokenKnob())
^
Found 1 error in 1 file (checked 1 source file)
不幸的是,它没有提供任何关于为什么BrokenKnob 不兼容的信息:在这种情况下,它缺少.frob()。如果没有这些信息,在不平凡的程序(使用具有多种方法和多种实现的协议)中纠正此类问题将变得非常乏味。
有没有办法在不修改程序的情况下从 mypy 或任何其他工具 获取这些信息?我知道我可以显式继承 Frobbable,但这完全违背了使用 Protocol 的目的。
【问题讨论】:
-
我不确定一个协议是否意味着那么复杂。为什么一个协议需要很多方法?
-
@chepner 为什么任何对象都需要不止一种方法?如果你尝试的话,我相信你能想到一些原因。但问题不在于这个。
-
协议比普通课程更专注。如果您传递给
main的东西非常具体以至于它需要支持许多方法,那么您可能需要一个特定的(子)类,而不是协议。