web-dev-qa-db-ja.com

Pythonでインターフェイスを実装するにはどうすればよいですか?

public interface IInterface
{
    void show();
}

 public class MyClass : IInterface
{

    #region IInterface Members

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

    #endregion
}

このC#コードに相当するPythonを実装するにはどうすればよいですか?

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!'

これはいい考えですか??あなたの答えに例を挙げてください。

129
Pratik Deoghare

ここで他の人が言及したように:

Pythonではインターフェイスは必要ありません。これは、Pythonには適切な多重継承があり、ダックタイピングもあるためです。つまり、mustの場所にJavaのインターフェイスがあり、Pythonにそれらを持っている必要はありません。

とはいえ、インターフェースにはまだいくつかの用途があります。それらのいくつかは、Python 2.6で導入されたPythonの抽象基本クラスでカバーされています。インスタンス化できない基本クラスを作成したいが、特定のインターフェースまたは実装の一部を提供したい場合に便利です。

別の使用法は、オブジェクトが特定のインターフェイスを実装することを何らかの方法で指定したい場合で、サブクラス化することでABCも使用できます。もう1つの方法はzope.interfaceです。これは、Zopeコンポーネントアーキテクチャの一部であるモジュールであり、非常に優れたコンポーネントフレームワークです。ここでは、インターフェイスからサブクラス化するのではなく、クラス(またはインスタンス)をインターフェイスの実装としてマークします。これは、コンポーネントレジストリからコンポーネントを検索するためにも使用できます。超クール!

113
Lennart Regebro

抽象基本クラスに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()
53
Peter Torpman

Pythonのインターフェイスのサードパーティの実装があります(最も一般的なのは Zope'sTwisted でも使用されます)が、より一般的にはPythonコーダーは、「抽象基底クラス」(ABC)として知られるより豊かな概念を使用することを好みます。これは、インターフェースを実装側面を持つ可能性と組み合わせます。 ABCはPython 2.6以降で特によくサポートされています。 the PEP を参照してください。ただし、以前のバージョンのPythonでも、通常は「方法サブクラスがそれらのメソッドをオーバーライドした方がよいことに気づくように、メソッドのいくつかがNotImplementedErrorを上げるクラスを定義するだけです!-)

26
Alex Martelli

インターフェース は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
19
blueray

このようなもの(周りにPythonがないのでうまくいかないかもしれません):

class IInterface:
    def show(self): raise NotImplementedError

class MyClass(IInterface):
    def show(self): print "Hello World!"
18
Bandi-T

現代の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の投稿 に触発されました。)

15
mrts

私の理解では、Pythonのような動的言語ではインターフェースはそれほど必要ではありません。 Java(またはC++とその抽象基本クラス)インターフェースは、たとえば一連のタスクを実行できる適切なパラメーターを渡します。

例えば。オブザーバーとオブザーバブルがある場合、オブザーバブルはIObserverインターフェイスをサポートするオブジェクトのサブスクライブに関心があり、そのオブジェクトにはnotifyアクションがあります。これはコンパイル時にチェックされます。

Pythonでは、compile timeのようなものはなく、メソッド検索は実行時に実行されます。さらに、__ getattr __()または__getattribute __()マジックメソッドを使用してルックアップをオーバーライドできます。つまり、notify属性にアクセスするとcallableを返すことができるオブジェクトをオブザーバーとして渡すことができます。

これにより、Pythonのインターフェース存在する-実際に使用される瞬間にそれらの実施が延期されるという結論に至ります。

7