gpt4 book ai didi

python - 我可以使用 Mypy stub 作为接口(interface)吗?

转载 作者:行者123 更新时间:2023-12-05 03:01:15 25 4
gpt4 key购买 nike

Mypy 允许我们编写 class stubs可以放在与实际类相同的目录中。这个 stub 与其他语言中已知的接口(interface)非常相似。是否可以让客户端使用 stub 并严格按照 stub 执行?

我想工作的例子:

class IDependency:
def do_something(self) -> None: ...
def do_something_else(self) -> None: ...

class Service:
def __init__(self, dependency: IDependency):
dependency.do_something()
dependency.do_something_else() # this fails silently

class DependencyImplementation(IDependency):
def do_something(self) -> None:
print("doing something")

# Note there is no `do_something_else` here.

这行得通。但是,如果 DependencyImplementation 没有实现 do_something 方法,则 Mypy 和 Python 本身都不会出错。这个电话什么都不做。我是否必须编写 raise NotImplementedException() 或使用 @abc.abstractmethod 注释每个方法才能工作? Mypy 或 Python 解释器中是否有一些特殊标志?

这是 Mypy Protocols 的用例吗? ?它似乎即将推出(也许是 Python 4?)

最佳答案

这确实是您可以使用 @abc.abstractmethod 或协议(protocol)来完成的事情。前者类似于使用 Java 的抽象类;后者类似于使用 Go 的接口(interface)或 Rust 特性。

这是一个使用 ABC 的例子:

from abc import abstractmethod

class Parent:
@abstractmethod
def foo(self) -> None: ...

# Missing an implementation for 'foo'!
class Child(Parent): pass

print(Child()) # Error: Cannot instantiate abstract class 'Child' with abstract attribute 'foo'

关于这个例子的一些注意事项:

  1. 您在 Child 类的实例化 中遇到错误,而不是在声明中。这是为了支持您从不实例化 Child 而是再次对其进行子类化并在第二个子类中定义 foo 的用例。
  2. 我们不需要将通常的 abc 元类添加到 Parent(例如 class Parent(metaclass=ABCMeta)):mypy 将理解 @abc .abstractmethod 表示有或没有它。仅当您希望 Python 解释器也强制您在运行时正确覆盖任何标记为抽象的内容时,才包含元类。
  3. ABC 不完全是接口(interface)——您仍然可以定义字段和非抽象方法。它们更类似于 Java 风格的抽象类。

您也可以使用协议(protocol),但现在您需要先pip install typing_extensions 才能使用它。这是一个例子:

from typing_extensions import Protocol

class CanFoo(Protocol):
def foo(self) -> None: ...

class Child: pass

def expects_fooable(x: CanFoo) -> None: ...

x = Child()
expects_fooable(x) # Error: Argument 1 to "expects_fooable" has incompatible type "Child"; expected "CanFoo"

一些注意事项:

  1. 这里,Child 故意不继承 CanFoo:类和它实现的协议(protocol)之间没有明确的联系:协议(protocol)与 Go 非常相似-style 接口(interface),并且可以更特别。将此与 Java 等语言进行对比,您确实需要在类定义中包含“implements Blah”。
  2. 与之前的错误不同,我们在 Child 的实例化中没有遇到错误:它本身没有任何错误。相反,当我们尝试不正确地使用它时,我们会得到一个异常。

一些最后的说明:

  1. stub 文件可能表面上看起来像接口(interface),但实际上并非如此:它们更像是一种将类型引入我们无法轻易修改和添加类型提示的代码的方式。您可以认为它们与 C 风格的头文件有些相似:这是一种独立于源代码存储现有对象签名的方式。
  2. “Typeshed”是一个 specific project 的名称其中包括标准库的 stub 和一些流行的第 3 方模块。该词不是“ stub 文件”的同义词。同样,术语“类 stub ”也有点用词不当:只有 stub 文件,其中可能包含也可能不包含类的定义。 (如果您尝试键入的原始 Python 或 C 扩展库仅包含函数,则相应的 stub 文件也可能仅包含这些函数的签名。)

关于python - 我可以使用 Mypy stub 作为接口(interface)吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56071609/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com