我可以使用Mypy存根作为接口吗?

2024-06-03 02:30:55 发布

您现在位置:Python中文网/ 问答频道 /正文

Mypy允许我们编写class stubs,它可以放在与实际类相同的目录中。这个存根非常类似于其他语言中已知的接口。有没有可能让客户机使用存根而实现严格遵循存根?在

我想工作的例子:

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解释器中有一些特殊的标志吗?在

这是Mypy Protocols的用例吗?它似乎很快就要发布了(也许是python4?)在


Tags: 方法self目录nonedefdependencydoelse
1条回答
网友
1楼 · 发布于 2024-06-03 02:30:55

这确实可以使用@abc.abstractmethod或协议来完成。前者类似于使用Java的抽象类;后者则类似于使用Go的接口或Rust特性。在

下面是一个使用ABCs的示例:

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. 在子类的实例化时会出错,而不是在声明中。这是为了支持这样一个用例:您从不实例化子类,而是再次将其子类化,并在第二个子类中定义foo。在
  2. 我们不需要将通常的abc元类添加到Parent(例如class Parent(metaclass=ABCMeta)):mypy可以理解@abc.abstractmethod有没有它意味着什么。只有当您希望Python解释器也强制您在运行时正确地重写了任何标记为抽象的内容时,才包含元类。在
  3. abc并不完全是接口,你仍然可以定义字段和非抽象方法。它们更类似于Java风格的抽象类。在

您也可以使用协议,不过现在您需要先pip install typing_extensions才能使用它。下面是一个例子:

^{pr2}$

一些注意事项:

  1. 在这里,Child故意不从CanFoo继承:在类和它实现的协议之间没有显式的链接:协议非常类似于Go风格的接口,并且可以更特别。与Java等语言相比,Java确实需要在类定义中包含“implements Blah”。在
  2. 与前面的错误不同,我们在Child的实例化上没有得到错误:它本身没有任何错误。相反,当我们试图不恰当地使用它时,我们会得到一个例外。在

最后几点提示:

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

相关问题 更多 >