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

休伯特·格热斯科维克

Mypy允许我们编写可以与实际类放在同一目录中的类存根该存根与其他语言中的接口非常相似。客户端可以使用存根,并且实现严格遵循存根吗?

示例我想工作:

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协议的用例吗?它似乎即将到来(也许是Python 4?)

迈克尔0x2a

实际上,您可以使用@abc.abstractmethod或协议来执行此操作前者类似于使用Java的抽象类。后者将类似于使用Go的界面或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并不是完全的接口-您仍然可以定义字段和非抽象方法。它们更类似于Java风格的抽象类。

您也可以使用协议,尽管现在您需要先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:类与它所实现的协议之间没有明确的链接:协议与Go风格的接口非常相似,并且可以是临时的。将此与Java之类的语言进行对比,您确实需要在类定义中包括“ implements Blah”。
  2. 与先前的错误不同,我们不会在的实例化上得到错误Child:它没有内在的错误。相反,当我们尝试不正确使用它时,我们会得到一个例外。

最后几点注意事项:

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

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

我可以使用HTML元素作为对象键吗?

我可以使用集合类型作为数组索引吗?

我可以使用枚举作为结构名称吗?

我可以使用cd ../ ..作为别名吗?

我可以使用张量作为列表索引吗?

我可以使用相同的dbcontext作为ASP身份吗

我可以使用 IEnumerator 作为更新函数吗?

我可以使用Apache Camel作为ESB吗?

我可以使用Aerospike作为持久层吗

我可以使用元组作为映射的键吗?

我可以使用VARCHAR作为主键吗?

我可以使用void *作为函数的参数吗?

我们可以使用类作为标题吗

我可以使用反向迭代器作为 ForwardIt 吗?

编写可能最终传递任何类型的结构的函数时,可以使用接口作为参数吗?

我可以使用 csv 文件作为我网站要使用哪些图像的参考吗?

我可以使用4 + 4 CPU接口为图形卡供电吗

我可以使用moq Mock <MyClass>来模拟类,而不是接口吗?

我可以使用接口类强制定义特定的构造函数吗?

我可以使用可从Java实现Java接口的scala类吗?

我可以使用嵌套接口模拟出库代码吗?

我可以使用继承而不是在策略模式中实现接口吗?

我可以使用带有接口而不是类的nestjs注入吗?

我可以使用我的功能作为“ negroni”中间件吗?

我可以使用我的电子邮件地址作为RabbitMQ用户名吗?

我可以使用任何文件作为我的游戏数据库吗?

我的朋友可以使用我本地的git仓库作为他的远程仓库吗?

我可以使用 oozie 操作作为我多次调用的模板吗?

我可以使用 `distance` 作为我的类成员变量名吗?