用于文档的 Python 接口

Dav*_*nan 1 python interface python-3.x

我知道在 Python 中我们使用鸭子类型而不是实现一个具体的接口。

因此,如果您有一个函数接收需要能够进食和饮水的动物对象,您只需调用.eat()and.drink()和传入的任何对象,只需确保以任何适合它们的方式包含这些方法。

调用您的函数时,无需制作每个人都实现的接口。

但是为了文档和新的 Python3 类型提示,是否有任何正确的方法来创建接口。

就像是 ...

interface Animal:
    eat()
    drink()

def foo(a: Animal):
    a.eat()
    a.drink()
Run Code Online (Sandbox Code Playgroud)

...其中接口Animal纯粹用于文档和foo函数中的非强制类型提示。它永远不会在运行时使用,那些将动物传入函数的人仍然遵循鸭子类型协议。

这在 Python 中可能吗?

blu*_*eth 5

您可以为此使用 ABC(抽象基类)。基类(读作“接口”)需要metaclass设置为abc.ABCMeta,或者派生自具有该功能的东西。然后,您可以使用装饰器来指示必须覆盖方法。

import abc

class Animal(metaclass=abc.ABCMeta):
    @abc.abstractmethod
    def eat(self):
        pass

    @abc.abstractmethod
    def drink(self):
        pass

def foo(a: Animal):
    a.eat()
    a.drink()
Run Code Online (Sandbox Code Playgroud)

属性、类方法和静态方法也可以通过使用之前 的普通装饰器来抽象@abc.abstractmethod

@property
@abc.abstractmethod
def data(self):
    return self._data

@classmethod
@abc.abstractmethod
def abstract_classmethod(cls, ...):
    pass

@staticmethod
@abc.abstractmethod
def abstract_staticmethod(...):
    pass
Run Code Online (Sandbox Code Playgroud)

这里正在使用...

In [40]: class Animal(metaclass=ABCMeta):
    ...:     @abstractmethod
    ...:     def eat(self):
    ...:         print('Eats...')
    ...:     @abstractmethod
    ...:     def drink(self):
    ...:         print('Drinks...')
    ...:
    ...:

In [41]: def foo(a: Animal):
    ...:     a.eat()
    ...:

In [42]: class Elephant:
    ...:     def eat(self):
    ...:         print('Elephant eating...')
    ...:     def drink(self):
    ...:         print('Elephant drinking...')
    ...:


In [43]: class Giraffe(Animal):
    ...:     def eat(self):
    ...:         print('Giraffe eats...')
    ...:     def drink(self):
    ...:         print('Giraffe drinks...')
    ...:

In [44]: giraffe = Giraffe()

In [45]: elephant = Elephant()

In [46]: isinstance(giraffe, Animal)
Out[46]: True

In [47]: isinstance(elephant, Animal)
Out[47]: False

In [48]: foo
Out[48]: <function __main__.foo(a: __main__.Animal)>

In [49]: foo(giraffe)
Giraffe eats...

In [50]: foo(elephant)
Elephant eating...

In [51]: foo(Animal())
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-51-e060be6dff03> in <module>
----> 1 foo(Animal())

TypeError: Can't instantiate abstract class Animal with abstract methods drink, eat
Run Code Online (Sandbox Code Playgroud)