如何在Python中实现接口?如何在Python中实现接口?(How do I implement

2019-06-17 09:58发布

public interface IInterface
{
    void show();
}

 public class MyClass : IInterface
{

    #region IInterface Members

    public void show()
    {
        Console.WriteLine("Hello World!");
    }

    #endregion
}

如何实现的Python相当于此C#代码?

class IInterface(object):
    def __init__(self):
        pass

    def show(self):
        raise Exception("NotImplementedException")


class MyClass(IInterface):
   def __init__(self):
       IInterface.__init__(self)

   def show(self):
       print 'Hello World!'

这是一个好主意吗?? 请给你的答案的例子。

Answer 1:

如前所述其他位置:

接口是没有必要在Python。 这是因为Python有适当的多重继承,而且鸭子类型,这意味着,你必须在Java接口的地方,你不必让他们在Python。

尽管如此,仍然有多种用途的接口。 他们中的一些是由蟒蛇抽象基类,在Python 2.6引入了覆盖。 他们是有用的,如果你想的是不能被实例化基类,而是提供一个实现的特定接口或部分。

另一种用法是,如果你以某种方式要指定一个对象实现特定的接口,你可以使用ABC的也太由他们继承。 另一种方式是zope.interface,一个模块是Zope的组件架构,一个非常酷赫然组件框架的一部分。 在这里,你不从接口继承,而是标志着类(甚至实例)作为实现一个接口。 这也可以用来从一个单元记录查找组件。 超酷!



Answer 2:

使用ABC模块抽象基类,似乎这样的伎俩。

from abc import ABCMeta, abstractmethod

class IInterface:
    __metaclass__ = ABCMeta

    @classmethod
    def version(self): return "1.0"
    @abstractmethod
    def show(self): raise NotImplementedError

class MyServer(IInterface):
    def show(self):
        print 'Hello, World 2!'

class MyBadServer(object):
    def show(self):
        print 'Damn you, world!'


class MyClient(object):

    def __init__(self, server):
        if not isinstance(server, IInterface): raise Exception('Bad interface')
        if not IInterface.version() == '1.0': raise Exception('Bad revision')

        self._server = server


    def client_show(self):
        self._server.show()


# This call will fail with an exception
try:
    x = MyClient(MyBadServer)
except Exception as exc:
    print 'Failed as it should!'

# This will pass with glory
MyClient(MyServer()).client_show()


Answer 3:

Python目前有接口的第三方实现(最流行的是Zope的 ,在同时使用双绞线 ),但更常见的Python程序员喜欢使用被称为“抽象基类”(ABC),这与融合的接口更丰富的概念有一些执行方面有太多的可能性。 基本知识都特别支持在Python 2.6和更高版本,看到的PEP ,但即使在早期版本的Python他们通常被视为“要走的路” -只是定义一个类,它的一些方法提高NotImplementedError ,这样子会要注意,他们最好覆盖这些方法 - !)



Answer 4:

像这样的东西(因为我没有Python的周围可能无法正常工作):

class IInterface:
    def show(self): raise NotImplementedError

class MyClass(IInterface):
    def show(self): print "Hello World!"


Answer 5:

接口支持Python 2.7和Python 3.4+。

要安装界面,你必须

pip install python-interface

示例代码:

from interface import implements, Interface

class MyInterface(Interface):

    def method1(self, x):
        pass

    def method2(self, x, y):
        pass


class MyClass(implements(MyInterface)):

    def method1(self, x):
        return x * 2

    def method2(self, x, y):
        return x + y


Answer 6:

抽象基类实现接口是现代Python 3的要简单得多,他们服务于一个目的,作为插件扩展接口的合同。

创建接口/抽象基类:

from abc import ABC, abstractmethod

class AccountingSystem(ABC):

    @abstractmethod
    def create_purchase_invoice(self, purchase):
        pass

    @abstractmethod
    def create_sale_invoice(self, sale):
        log.debug('Creating sale invoice', sale)

创建一个正常的子类,并覆盖所有的抽象方法:

class GizmoAccountingSystem(AccountingSystem):

    def create_purchase_invoice(self, purchase):
        submit_to_gizmo_purchase_service(purchase)

    def create_sale_invoice(self, sale):
        super().create_sale_invoice(sale)
        submit_to_gizmo_sale_service(sale)

您可以选择在抽象方法作为通用的实现create_sale_invoice()以调用它super()明确与上述子类。

子类的实例化没有实现所有的抽象方法失败:

class IncompleteAccountingSystem(AccountingSystem):
    pass

>>> accounting = IncompleteAccountingSystem()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: Can't instantiate abstract class IncompleteAccountingSystem with abstract methods
create_purchase_invoice, create_sale_invoice

您还可以通过相应的注解相结合具有抽象性,静态和类方法@abstractmethod

抽象基类是伟大的实现基于插件的系统。 一个类的所有进口的子类都可以通过访问__subclasses__()所以如果你有一个插件目录中加载的所有类importlib.import_module()如果他们继承的基类,您可以通过直接访问它们__subclasses__()您可以确保实例化过程中的界面合同强制执行他们。

下面是该插件加载实现AccountingSystem上面的例子:

...
from importlib import import_module

class AccountingSystem(ABC):

    ...
    _instance = None

    @classmethod
    def instance(cls):
        if not cls._instance:
            module_name = settings.ACCOUNTING_SYSTEM_MODULE_NAME
            import_module(module_name)
            subclasses = cls.__subclasses__()
            if len(subclasses) > 1:
                raise InvalidAccountingSystemError('More than one '
                        f'accounting module: {subclasses}')
            if not subclasses or module_name not in str(subclasses[0]):
                raise InvalidAccountingSystemError('Accounting module '
                        f'{module_name} does not exist or does not '
                        'subclass AccountingSystem')
            cls._instance = subclasses[0]()
        return cls._instance

然后,您可以通过访问会计系统插件对象AccountingSystem类:

>>> accountingsystem = AccountingSystem.instance()

(由启发本PyMOTW-3柱 )。



Answer 7:

我的理解是,接口并不像Python的动态语言是必要的。 在Java(或C ++以其抽象基类)接口装置,确保如要传递正确的参数,能够完成一组任务。

例如,如果您有观察者和观察的,观察到的是有意认购支持IObserver接口,这反过来又对象notify行动。 这是在编译期进行检查。

在Python,没有这样的东西作为compile time和方法查找在运行时执行。 此外,一个可以与__getattr __()或__getattribute __()魔术方法覆盖的查找。 换句话说,你可以传递,作为观察员,可在访问返回调用任何对象notify属性。

这使我得出结论,即在Python接口确实存在 -它只是他们的执法推迟到它们被实际使用的那一刻



文章来源: How do I implement interfaces in python?
标签: python oop