Pertanyaan Bagaimana cara mengimplementasikan antarmuka dalam python?


public interface IInterface
{
    void show();
}

 public class MyClass : IInterface
{

    #region IInterface Members

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

    #endregion
}

Bagaimana cara menerapkan Python yang setara dengan kode C # ini?

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

Apakah ini ide yang bagus ?? Tolong beri contoh dalam jawaban Anda.


75
2018-01-23 18:29


asal


Jawaban:


Seperti yang disebutkan oleh yang lain di sini:

Antarmuka tidak diperlukan dalam Python. Ini karena Python memiliki multiple inheritance yang tepat, dan juga ducktyping, yang berarti tempat-tempat di mana Anda harus memiliki antarmuka di Java, Anda tidak harus memilikinya dengan Python.

Yang mengatakan, masih ada beberapa kegunaan untuk antarmuka. Beberapa dari mereka ditutupi oleh Pythons Abstrak Kelas Base, diperkenalkan dengan Python 2.6. Mereka berguna, jika Anda ingin membuat kelas dasar yang tidak dapat dipakai, tetapi menyediakan antarmuka khusus atau bagian dari suatu implementasi.

Penggunaan lain adalah jika Anda ingin menentukan bahwa objek mengimplementasikan antarmuka tertentu, dan Anda dapat menggunakan ABC untuk itu juga dengan subclassing dari mereka. Cara lain adalah zope.interface, modul yang merupakan bagian dari Zope Component Architecture, kerangka komponen yang benar-benar luar biasa kerennya. Di sini Anda tidak melakukan subkelas dari antarmuka, tetapi sebagai gantinya menandai kelas (atau bahkan instance) sebagai menerapkan antarmuka. Ini juga dapat digunakan untuk mencari komponen dari registri komponen. Sangat keren!


71
2018-01-23 19:35



Menggunakan modul abc untuk kelas dasar abstrak tampaknya melakukan trik.

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()

25
2018-04-17 13:11



Ada implementasi antarmuka pihak ketiga untuk Python (paling populer adalah Zope, juga digunakan dalam Memutar), tetapi coders Python lebih umum lebih suka menggunakan konsep yang lebih kaya yang dikenal sebagai "Abstrak Base Class" (ABC), yang menggabungkan antarmuka dengan kemungkinan memiliki beberapa aspek implementasi di sana juga. ABC sangat didukung dengan Python 2.6 dan kemudian, lihat PEP, tetapi bahkan dalam versi Python sebelumnya mereka biasanya dilihat sebagai "jalan untuk pergi" - hanya mendefinisikan kelas beberapa metode yang meningkatkan NotImplementedError sehingga subclass akan berada di pemberitahuan bahwa mereka sebaiknya menimpa metode tersebut! -)


19
2018-01-23 18:33



Sesuatu seperti ini (mungkin tidak berfungsi karena saya tidak memiliki Python di sekitar):

class IInterface:
    def show(self): raise NotImplementedError

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

13
2018-01-23 18:36



Pemahaman saya adalah bahwa antarmuka tidak diperlukan dalam bahasa dinamis seperti Python. Di Java (atau C ++ dengan antarmuka kelas abstraknya) adalah sarana untuk memastikan bahwa mis. Anda melewatkan parameter yang tepat, mampu melakukan serangkaian tugas.

Misalnya. jika Anda memiliki pengamat dan dapat diamati, diamati tertarik dalam berlangganan objek yang mendukung antarmuka IObserver, yang pada gilirannya memiliki notify tindakan. Ini diperiksa pada waktu kompilasi.

Dalam Python, tidak ada hal seperti itu compile time dan pencarian metode dilakukan saat runtime. Selain itu, seseorang dapat menimpa pencarian dengan metode ajaib __getattr __ () atau __getattribute __ (). Dengan kata lain, Anda dapat lulus, sebagai pengamat, objek apa pun yang dapat mengembalikan callable pada akses notify atribut.

Ini membawa saya pada kesimpulan, bahwa antarmuka dengan Python memang ada - hanya saja penegakannya ditunda ke saat di mana mereka benar-benar digunakan


6
2018-01-23 19:19



Menerapkan antarmuka dengan kelas dasar abstrak jauh lebih sederhana dalam Python 3 modern dan mereka melayani tujuan sebagai kontrak antarmuka untuk ekstensi plug-in.

Buat antarmuka / kelas dasar abstrak:

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)

Buat subkelas normal dan timpa semua metode abstrak:

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)

Anda dapat secara opsional memiliki implementasi umum dalam metode abstrak seperti pada create_sale_invoice(), memanggilnya dengan super() secara eksplisit di subclass seperti di atas.

Instansiasi dari subclass yang tidak mengimplementasikan semua metode abstrak gagal:

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

Anda juga dapat memiliki properti abstrak, metode statis dan kelas dengan menggabungkan anotasi terkait dengan @abstractmethod.

Kelas dasar abstrak sangat bagus untuk menerapkan sistem berbasis plugin. Semua subclass yang diimpor dari kelas dapat diakses melalui __subclasses__(), jadi jika Anda memuat semua kelas dari direktori plugin dengan importlib.import_module() dan jika mereka subclass kelas dasar, Anda memiliki akses langsung kepada mereka melalui __subclasses__() dan Anda dapat yakin bahwa kontrak antarmuka diberlakukan untuk semuanya selama instantiasi.

Berikut ini implementasi pemuatan plugin untuk AccountingSystem contoh di atas:

...
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

Kemudian Anda dapat mengakses objek plugin sistem akuntansi melalui AccountingSystem kelas:

>>> accountingsystem = AccountingSystem.instance()

(Terinspirasi oleh pos PyMOTW-3 ini.)


0
2017-07-10 20:06