exh*_*uma 6 python type-hinting python-typing
以下代码定义了一个简单的协议和一个几乎实现该协议的类。唯一的区别是该run()方法在协议中接受一个参数,但它不是以这种方式实现的。
然而,isinstance()检查返回 true,这是出乎意料的。
据我了解PEP-544这应该有效。尽管检查函数签名还不清楚。
当在成员中使用错误的数据类型(例如,在协议中将ORDER其更改为)时,也会发生同样的问题。str
我知道类型提示只是......嗯......“提示”并且在运行时不会强制执行。
但是,在我的应用程序中,确保某些类遵循定义的协议以获得更清晰的错误消息将很有用。它使用插件架构,加载插件后,如果该插件遵循所需的协议,则进行快速“健全性检查”会很有用,如果没有,则提供早期且有用的错误消息,而不是导致异常稍后在下游。
from typing_extensions import Protocol, runtime_checkable
@runtime_checkable
class PFoo(Protocol):
ORDER: int
def run(self, a: int) -> None:
...
class Hello:
ORDER = 10
def run(self) -> None:
print(1)
# Returns "True" evn though the signature of "run()" doesn't match
print(isinstance(Hello(), PFoo))
Run Code Online (Sandbox Code Playgroud)
这是模块runtime_checkable中函数的文档字符串:typing
"""Mark a protocol class as a runtime protocol.\n\nSuch protocol can be used with isinstance() and issubclass().\nRaise TypeError if applied to a non-protocol class.\nThis allows a simple-minded structural check very similar to\none trick ponies in collections.abc such as Iterable.\nFor example::\n\n @runtime_checkable\n class Closable(Protocol):\n def close(self): ...\n\n assert isinstance(open(\'/some/file\'), Closable)\n\nWarning: this will check only the presence of the required methods,\nnot their type signatures!\n"""\nRun Code Online (Sandbox Code Playgroud)\n如果要比较函数的类型注释,可以检查__annotations__函数的属性(如果它是已from __future__ import annotations启用的模块,则最好typing.get_type_hints在函数上使用而不是__annotations__直接检查属性)。如果您正在寻找精确的签名匹配,则可以使用模块 \xe2\x80\x94 文档signature中的函数(此处)。注意:我认为使用可能会产生一些运行时性能成本(但话又说回来,所有运行时类型检查也是如此)。inspectinspect.signature