मैं अजगर में इंटरफेस कैसे लागू करूं?


182
public interface IInterface
{
    void show();
}

 public class MyClass : IInterface
{

    #region IInterface Members

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

    #endregion
}

मैं इस 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!'

यह एक अच्छा विचार है?? कृपया अपने उत्तरों में उदाहरण दें।


आपके मामले में एक इंटरफ़ेस का उपयोग करने का उद्देश्य क्या होगा?
बांदी-टी

23
खुलकर कोई उद्देश्य नहीं! मैं बस सीखना चाहता हूं कि जब आपको अजगर में इंटरफेस की आवश्यकता हो तो क्या करना चाहिए?
प्रतीक देवघर २३'१० को १३:१३

18
raise NotImplementedErrorजब showशरीर को पूरी तरह से सामान्य उठाने का कोई मतलब नहीं है, Exceptionजब पायथन पूरी तरह से विशिष्ट एक में निर्मित! -)
एलेक्स मार्टेली

2
IInterface में init call show () नहीं होना चाहिए (या अपवाद को स्वयं उठाना) ताकि आप अमूर्त इंटरफ़ेस को तुरंत न देख सकें?
काटास्टिक वॉयज

1
मैं इसके लिए कुछ उपयोग देख सकता हूं ... मान लीजिए कि आपके पास एक वस्तु है जिसे आप एक विशिष्ट हस्ताक्षर सुनिश्चित करना चाहते हैं। बतख टाइपिंग के साथ आप यह गारंटी नहीं दे सकते हैं कि ऑब्जेक्ट उस हस्ताक्षर का होगा जिसकी आप अपेक्षा करते हैं। कभी-कभी यह गतिशील रूप से टाइप किए गए गुणों पर कुछ टाइपिंग को लागू करने के लिए उपयोगी हो सकता है।
प्राइम बाय डिजाईन

जवाबों:


151

जैसा कि यहां अन्य ने उल्लेख किया है:

पायथन में इंटरफेस जरूरी नहीं है। इसका कारण यह है कि पायथन के पास उचित बहु विरासत है, और साथ ही ducktyping भी है, जिसका अर्थ है कि जिन जगहों पर आपके पास जावा में इंटरफेस होना चाहिए , आपको उन्हें पायथन में रखने की आवश्यकता नहीं है।

उस ने कहा, इंटरफेस के लिए अभी भी कई उपयोग हैं। उनमें से कुछ Pythons Abstract Base Classes द्वारा कवर किए गए हैं, जिन्हें Python 2.6 में पेश किया गया है। वे उपयोगी होते हैं, यदि आप आधार कक्षाएं बनाना चाहते हैं जो कि त्वरित नहीं हो सकते हैं, लेकिन एक विशिष्ट इंटरफ़ेस या कार्यान्वयन का हिस्सा प्रदान करते हैं।

एक अन्य उपयोग यह है कि यदि आप किसी तरह यह निर्दिष्ट करना चाहते हैं कि एक वस्तु एक विशिष्ट इंटरफ़ेस लागू करती है, और आप एबीसी के लिए भी उनका उपयोग कर सकते हैं। एक और तरीका है zope.interface, एक मॉड्यूल जो कि Zope Component Architecture का एक हिस्सा है, वास्तव में एक बहुत ही अच्छा ठंडा फ्रेमवर्क है। यहाँ आप इंटरफेस से उप-वर्ग नहीं करते हैं, बल्कि इंटरफ़ेस लागू करने के रूप में कक्षाओं (या यहां तक ​​कि उदाहरण) को चिह्नित करते हैं। यह एक घटक रजिस्ट्री से घटकों को देखने के लिए भी इस्तेमाल किया जा सकता है। बेहद कूल!


11
क्या आपक लिए इसे विस्तार से कहना संभव है? 1. कोई इस तरह के इंटरफ़ेस को कैसे लागू करता है? 2. इसका उपयोग घटकों को देखने के लिए कैसे किया जा सकता है?
जियोसाइसिक

43
"पायथन में इंटरफेस आवश्यक नहीं हैं। जब वे होते हैं तब को छोड़कर।"
बैपटिस्ट कैंडेलियर

8
इंटरफेस का उपयोग ज्यादातर वस्तुओं के पास होने पर एक अनुमानित परिणाम / सदस्यों की शुद्धता को लागू करने के लिए किया जाता है। यह बहुत अच्छा होगा अगर अजगर एक विकल्प के रूप में इसका समर्थन करता है। यह भी विकास उपकरण बेहतर IntelliSense है करने की अनुमति होगी
ध्वनि आत्मा

1
एक उदाहरण से इस उत्तर में बहुत सुधार होगा।
बॉब

5
"यह इसलिए है क्योंकि पायथन के पास उचित बहु विरासत है", किसने कहा कि कई विरासत के लिए इंटरफेस हैं?
अदनमुट्टलेब

76

एब्सट्रैक्ट बेस क्लासेस के लिए एबीसी मॉड्यूल का उपयोग करना ट्रिक लगता है।

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

11
युग, जो भाषा का हिस्सा होना चाहिए, उसके लिए कुछ मॉड्यूल की आवश्यकता है, या इसका उपयोग नहीं किया जाना चाहिए, IMO।
माइक डी क्लार्क

क्या आपका मतलब है if not server.version() == '1.0': raise ...:? मैं वास्तव में इस लाइन नहीं मिलता है। एक स्पष्टीकरण का स्वागत किया जाएगा।
स्कैंडिक्स

1
@MikedeKlerk मैं अधिक सहमत नहीं हो सका। जैसे अजगर टाइपिंग का जवाब देता है; मुझे यह घोषित करने के लिए एक मॉड्यूल का आयात नहीं करना चाहिए कि मैं एक प्रकार होना चाहता हूं। उस पर प्रतिक्रिया आम तौर पर "अच्छी तरह से पायथन गतिशील रूप से टाइप की जाती है", लेकिन यह एक बहाना नहीं है। Java + Groovy इस समस्या को हल करता है। स्थैतिक सामान के लिए जावा, गतिशील सामान के लिए ग्रूवी।
जुबिकैकोन

6
@MikedeKlerk, एबीसी मॉड्यूल वास्तव में अजगर के लिए बनाया गया है। इनमें से कुछ प्रतिमानों को स्थापित करना थोड़ा अधिक काम है क्योंकि वे वैकल्पिक पैटर्न के कारण पाइथन में अप्रभावित रहते हैं जिन्हें 'अधिक पाइथोनिक' माना जाता है। अधिकांश डेवलपर्स के लिए, यह ऐसा होगा जैसा आपने कहा, 'बिल्कुल इस्तेमाल नहीं किया गया।' हालांकि, यह स्वीकार करते हुए कि कुछ बहुत ही आला मामले हैं जिन्हें वास्तव में इन इंटरफेसिंग क्षमताओं की आवश्यकता होती है, पायथन रचनाकारों ने संभव बनाने के लिए एक आसान-से-उपयोग एपीआई प्रदान किया।
डेविड कूलब्रथ

39

इंटरफ़ेस पायथन 2.7 और पायथन 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

7
इस लाइब्रेरी का एक बड़ा फायदा, IMHO, यह शुरुआती विफलता है जो आपको देती है: यदि आपकी कक्षा एक निर्दिष्ट इंटरफ़ेस को सही ढंग से लागू नहीं करती है, तो आपको एक अपवाद मिलता है जैसे ही कक्षा में पढ़ा जाता है - आपको इसका उपयोग करने की आवश्यकता नहीं है । पायथन के अपने अमूर्त आधार वर्ग के साथ, आपको अपवाद तब मिलता है जब आप पहले अपनी कक्षा को त्वरित करते हैं, जो बहुत बाद में हो सकता है।
हंस

यह अनावश्यक है, एबीसी एक समान, अंतर्निहित कार्यक्षमता प्रदान करता है।
डैनियल

@DanielCasares एबीसी एक वास्तविक इंटरफ़ेस प्रदान करता है या क्या आपका मतलब है कि राज्य या कार्यान्वयन के बिना अमूर्त वर्ग समाधान है कि एबीसी प्रदान करता है?
asaf92

36

अमूर्त आधार वर्गों के साथ इंटरफेस को लागू करना आधुनिक पायथन 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 पोस्ट से प्रेरित )


प्रश्न: मॉड्यूल-नाम "एबीसी" किसके लिए है?
सेबेस्टियन नीलसन

"एबीसी" "सार आधार वर्ग" के लिए खड़ा है, को देखने के सरकारी डॉक्स
एमआरटीएस

31

पायथन के लिए इंटरफेस के तीसरे पक्ष के कार्यान्वयन हैं (सबसे लोकप्रिय ज़ोप्स है , जिसे मुड़ में भी इस्तेमाल किया जाता है ), लेकिन अधिक सामान्यतः पायथन कोडर्स "सार बेस क्लास" (एबीसी) के रूप में ज्ञात समृद्ध अवधारणा का उपयोग करना पसंद करते हैं, जो एक इंटरफ़ेस के साथ संयोजन करता है। वहाँ भी कुछ कार्यान्वयन पहलुओं की संभावना है। एबीसी पायथन 2.6 में विशेष रूप से अच्छी तरह से समर्थित हैं और बाद में, पीईपी देखते हैं , लेकिन पायथन के पहले के संस्करणों में भी वे आम तौर पर "जाने का रास्ता" के रूप में देखे जाते हैं - बस एक वर्ग को परिभाषित करते हैं, जिसके कुछ तरीकों को बढ़ाते हैं NotImplementedErrorताकि उपवर्ग होंगे ध्यान दें कि वे बेहतर तरीके से उन तरीकों को ओवरराइड करेंगे! -)


3
पायथन के लिए इंटरफेस के तीसरे पक्ष के कार्यान्वयन हैं इसका क्या मतलब है? क्या आप एबीसी की व्याख्या कर सकते हैं?
प्रतीक देवघर

2
ठीक है, मैं एबीसी के "अमीर" होने के साथ मुद्दा लूंगा। ;) वहाँ चीजें हैं zope.interface कर सकते हैं कि एबीसी के रूप में के रूप में अच्छी तरह से चारों ओर नहीं कर सकते हैं। लेकिन अन्यथा आप हमेशा की तरह सही हैं। +1
लेनार्ट रेगेब्रो

1
@ एकीकृत: इसका मतलब है कि मानक पुस्तकालय में zope.interface जैसे मॉड्यूल शामिल नहीं हैं, लेकिन यह पीपीआई से उपलब्ध है।
लेनार्ट रेगेब्रो

मेरे पास अभी भी एबीसी की अवधारणा को सुधारने के लिए कठिन समय है। क्या किसी के लिए एबीसी के संदर्भ में twistedmatrix.com/documents/current/core/howto/compords.html (IMHO, इंटरफेस अवधारणा का एक उत्कृष्ट विवरण) को फिर से लिखना संभव होगा । क्या इसका कोई मतलब है?
छल करें

21

कुछ इस तरह से हो सकता है (जैसे कि मेरे पास अजगर नहीं है)

class IInterface:
    def show(self): raise NotImplementedError

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

2
मुझे __init__(self)कंस्ट्रक्टर के बारे में क्या करना चाहिए ?
प्रतीक देवघर

1
आप पर निर्भर करता है। चूँकि किसी अमूर्त वर्ग से किसी वस्तु के निर्माण के खिलाफ कोई संकलन-समय की जाँच नहीं होती है इसलिए आपको कोडिंग / संकलन के दौरान कोई सुरक्षा प्राप्त नहीं होगी। एक कंस्ट्रक्टर विरासत में मिला होगा, इसलिए ऑब्जेक्ट बन जाएगा , बस "खाली" होना चाहिए। यह तय करना आपके ऊपर है कि क्या आप ऐसा होने से बेहतर होंगे और बाद में विफलताओं को पकड़ सकते हैं, या स्पष्ट रूप से कार्यक्रम को रोक सकते हैं और एक समान निर्माणकर्ता को एक अपवाद को लागू करने से।
बांडी-टी

1
यही कारण abc.ABCहै कि उठाने से बहुत बेहतर है NotImplementedError- एक abc.ABCउपवर्ग का तात्कालिकता जो सभी अमूर्त तरीकों को लागू नहीं करता है, जल्दी विफल हो जाता है, इसलिए आपको त्रुटियों से सुरक्षित किया जाता है। त्रुटि कैसी दिखती है, इसके लिए नीचे मेरा उत्तर देखें।
एमआरटीएस

8

मेरी समझ यह है कि इंटरफेस पायथन जैसे गतिशील भाषाओं में आवश्यक नहीं हैं। जावा में (या इसके मूल आधार वर्ग के साथ C ++) इंटरफेस यह सुनिश्चित करने के लिए साधन हैं कि जैसे आप सही पैरामीटर पास कर रहे हैं, कार्यों का सेट करने में सक्षम हैं।

उदाहरण के लिए, यदि आपके पास पर्यवेक्षक और अवलोकन योग्य है, तो ऑब्जर्वेबल उन वस्तुओं की सदस्यता लेने में रुचि रखता है जो IObserver इंटरफ़ेस का समर्थन करते हैं, जिसमें बदले में notifyकार्रवाई होती है। यह संकलन समय पर जांचा जाता है।

पाइथन में, compile timeरनटाइम पर मेथड लुकअप और मेथड देखने जैसी कोई चीज नहीं है। इसके अलावा, कोई __getattr __ () या __getattribute __ () जादू विधियों के साथ लुक को ओवरराइड कर सकता है। दूसरे शब्दों में, आप पर्यवेक्षक के रूप में पास कर सकते हैं, कोई भी वस्तु जो एक्सेस करने की notifyविशेषता पर कॉल करने योग्य वापस आ सकती है ।

यह मुझे इस निष्कर्ष पर पहुंचाता है, कि पायथन में इंटरफेस मौजूद हैं - यह सिर्फ उनका प्रवर्तन है जिस क्षण में वे वास्तव में उपयोग किए जाते हैं

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.