जवाबों:
आप कभी-कभी जो देखेंगे वह निम्नलिखित है:
class Abstract1( object ):
"""Some description that tells you it's abstract,
often listing the methods you're expected to supply."""
def aMethod( self ):
raise NotImplementedError( "Should have implemented this" )
क्योंकि पायथन के पास एक औपचारिक इंटरफ़ेस अनुबंध नहीं है (और इसकी आवश्यकता नहीं है), अमूर्त और इंटरफ़ेस के बीच जावा-शैली का अंतर मौजूद नहीं है। यदि कोई औपचारिक इंटरफ़ेस को परिभाषित करने के प्रयास से गुजरता है, तो यह एक अमूर्त वर्ग भी होगा। केवल अंतर डॉकस्ट्रिंग में वर्णित इरादे में होगा।
और सार और इंटरफ़ेस के बीच का अंतर एक हेयरस्प्लिंग बात है जब आपने डकार टाइपिंग की है।
जावा इंटरफेस का उपयोग करता है क्योंकि इसमें एकाधिक उत्तराधिकार नहीं है।
क्योंकि पायथन में कई विरासतें हैं, इसलिए आप कुछ इस तरह भी देख सकते हैं
class SomeAbstraction( object ):
pass # lots of stuff - but missing something
class Mixin1( object ):
def something( self ):
pass # one implementation
class Mixin2( object ):
def something( self ):
pass # another
class Concrete1( SomeAbstraction, Mixin1 ):
pass
class Concrete2( SomeAbstraction, Mixin2 ):
pass
यह कंक्रीट उपवर्ग बनाने के लिए मिश्रणों के साथ एक प्रकार के अमूर्त सुपरक्लास का उपयोग करता है जो कि घृणास्पद हैं।
NotImplementedError("Class %s doesn't implement aMethod()" % (self.__class__.__name__))
अधिक जानकारीपूर्ण त्रुटि संदेश है :)
पायथन में अमूर्त वर्ग और इंटरफ़ेस के बीच अंतर क्या है?
ऑब्जेक्ट के लिए एक इंटरफ़ेस, उस ऑब्जेक्ट पर विधियों और विशेषताओं का एक सेट है।
पायथन में, हम इंटरफ़ेस को परिभाषित करने और लागू करने के लिए एक सार आधार वर्ग का उपयोग कर सकते हैं।
उदाहरण के लिए, मान लें कि हम collections
मॉड्यूल से अमूर्त आधार वर्गों में से एक का उपयोग करना चाहते हैं :
import collections
class MySet(collections.Set):
pass
यदि हम इसका उपयोग करने का प्रयास करते हैं, तो हमें एक TypeError
कारण मिलता है क्योंकि हमने जो वर्ग बनाया है वह सेट के अपेक्षित व्यवहार का समर्थन नहीं करता है:
>>> MySet()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: Can't instantiate abstract class MySet with abstract methods
__contains__, __iter__, __len__
इसलिए हम पर लागू करने के लिए आवश्यक हैं कम से कम __contains__
, __iter__
और __len__
। आइए प्रलेखन से इस कार्यान्वयन उदाहरण का उपयोग करें :
class ListBasedSet(collections.Set):
"""Alternate set implementation favoring space over speed
and not requiring the set elements to be hashable.
"""
def __init__(self, iterable):
self.elements = lst = []
for value in iterable:
if value not in lst:
lst.append(value)
def __iter__(self):
return iter(self.elements)
def __contains__(self, value):
return value in self.elements
def __len__(self):
return len(self.elements)
s1 = ListBasedSet('abcdef')
s2 = ListBasedSet('defghi')
overlap = s1 & s2
हम प्रासंगिक तरीकों पर डेकोरेटर abc.ABCMeta
का उपयोग करके और मेटाक्लर की स्थापना करके अपना स्वयं का सार बेस क्लास बना सकते हैं abc.abstractmethod
। मेटाक्लास को सजाए गए कार्यों को __abstractmethods__
विशेषता में जोड़ा जाएगा , जब तक कि वे परिभाषित न हों, तब तक रोकना संभव है।
import abc
उदाहरण के लिए, "अपूरणीय" को किसी ऐसी चीज के रूप में परिभाषित किया जाता है जिसे शब्दों में व्यक्त किया जा सकता है। मान लें कि हम एक सार आधार वर्ग को परिभाषित करना चाहते हैं, जो कि पवित्र है, पायथन 2 में:
class Effable(object):
__metaclass__ = abc.ABCMeta
@abc.abstractmethod
def __str__(self):
raise NotImplementedError('users must define __str__ to use this base class')
या पायथन 3 में, मेटाक्लास घोषणा में थोड़े बदलाव के साथ:
class Effable(object, metaclass=abc.ABCMeta):
@abc.abstractmethod
def __str__(self):
raise NotImplementedError('users must define __str__ to use this base class')
अब यदि हम इंटरफ़ेस को लागू किए बिना एक पवित्र वस्तु बनाने की कोशिश करते हैं:
class MyEffable(Effable):
pass
और इसे तत्काल करने का प्रयास:
>>> MyEffable()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: Can't instantiate abstract class MyEffable with abstract methods __str__
हमें बताया गया है कि हमने काम पूरा नहीं किया है।
अब यदि हम अपेक्षित इंटरफ़ेस प्रदान करते हैं:
class MyEffable(Effable):
def __str__(self):
return 'expressable!'
हम तब सार से प्राप्त वर्ग के ठोस संस्करण का उपयोग करने में सक्षम हैं:
>>> me = MyEffable()
>>> print(me)
expressable!
इसके साथ हम कुछ अन्य चीजें भी कर सकते हैं, जैसे कि वर्चुअल उपवर्ग पंजीकृत करें जो पहले से ही इन इंटरफेस को लागू करते हैं, लेकिन मुझे लगता है कि यह इस सवाल के दायरे से बाहर है। abc
हालाँकि अन्य तरीकों का प्रदर्शन किया गया है, हालांकि, ऐसा करने के लिए मॉड्यूल का उपयोग करके इस पद्धति को अनुकूलित करना होगा ।
हमने प्रदर्शित किया है कि एक मूल बेस क्लास का निर्माण पायथन में कस्टम ऑब्जेक्ट्स के लिए इंटरफेस को परिभाषित करता है।
पायथन> = 2.6 में सार बेस कक्षाएं हैं ।
एब्सट्रैक्ट बेस (क्लासिफाइड एबीसी) डक-टाइपिंग को इंटरफेस को परिभाषित करने का एक तरीका प्रदान करके पूरक करता है जब अन्य तकनीक जैसे हैटट्र () अनाड़ी होगा। पायथन डेटा संरचनाओं (संग्रह मॉड्यूल में), संख्याओं (संख्या मॉड्यूल में), और धाराओं (io मॉड्यूल में) के लिए कई अंतर्निहित एबीसी के साथ आता है। आप एबीसी मॉड्यूल के साथ अपनी खुद की एबीसी बना सकते हैं।
वहाँ भी है Zope इंटरफेस मॉड्यूल है, जो मुड़ की तरह, zope के बाहर परियोजनाओं द्वारा प्रयोग किया जाता है। मैं वास्तव में इससे परिचित नहीं हूं, लेकिन यहां एक विकी पेज है जो मदद कर सकता है।
सामान्य तौर पर, आपको एब्स्ट्रैक्ट क्लासेस की अवधारणा की आवश्यकता नहीं है, या अजगर में इंटरफेस (संपादित करें - विवरणों के लिए S.Lott का उत्तर देखें)।
पायथन वास्तव में या तो अवधारणा नहीं है।
यह बतख टाइपिंग का उपयोग करता है, जिसने इंटरफेस की आवश्यकता को हटा दिया (कम से कम कंप्यूटर के लिए :-))
पायथन <= 2.5: बेस कक्षाएं स्पष्ट रूप से मौजूद हैं, लेकिन एक विधि को 'शुद्ध आभासी' के रूप में चिह्नित करने का कोई स्पष्ट तरीका नहीं है, इसलिए वर्ग वास्तव में सार नहीं है।
पायथन> = 2.6: सार आधार कक्षाएं मौजूद हैं ( http://docs.python.org/library/abc.html )। और आपको उन विधियों को निर्दिष्ट करने की अनुमति देता है जिन्हें उपवर्गों में लागू किया जाना चाहिए। मुझे सिंटैक्स पसंद नहीं है, लेकिन सुविधा है। अधिकांश समय यह संभव है कि 'ग्राहक' का उपयोग करके डक टाइपिंग का उपयोग करना बेहतर हो।
समझाने के लिए और अधिक बुनियादी तरीके से: एक इंटरफ़ेस एक खाली मफिन पैन की तरह है। यह एक वर्ग फ़ाइल है जिसमें ऐसी पद्धति परिभाषाएँ हैं जिनका कोई कोड नहीं है।
एक सार वर्ग एक ही बात है, लेकिन सभी कार्यों को खाली करने की आवश्यकता नहीं है। कुछ में कोड हो सकते हैं। यह सख्ती से खाली नहीं है।
अंतर क्यों: पायथन में बहुत व्यावहारिक अंतर नहीं है, लेकिन एक बड़े प्रोजेक्ट के लिए योजना स्तर पर, इंटरफेस के बारे में बात करना अधिक सामान्य हो सकता है, क्योंकि कोई कोड नहीं है। खासकर यदि आप जावा प्रोग्रामर के साथ काम कर रहे हैं जो शब्द के आदी हैं।
सामान्य तौर पर, इंटरफेस का उपयोग केवल उन भाषाओं में किया जाता है जो एकल-वंशानुक्रम वर्ग मॉडल का उपयोग करते हैं। इन एकल-विरासत भाषाओं में, इंटरफेस आमतौर पर उपयोग किए जाते हैं यदि कोई वर्ग किसी विशेष विधि या विधियों के सेट का उपयोग कर सकता है। इन एकल-विरासत भाषाओं में भी, अमूर्त वर्गों का उपयोग या तो किसी भी या अधिक विधियों के अतिरिक्त वर्ग चर को परिभाषित करने के लिए किया जाता है, या एकल-विरासत मॉडल का उपयोग उन वर्गों की श्रेणी को सीमित करने के लिए किया जाता है जो विधियों के एक सेट का उपयोग कर सकते हैं।
एकाधिक-वंशानुक्रम मॉडल का समर्थन करने वाली भाषाएं केवल कक्षाओं या सार आधार वर्गों का उपयोग करती हैं और इंटरफेस नहीं। चूंकि पायथन कई विरासतों का समर्थन करता है, इसलिए यह इंटरफेस का उपयोग नहीं करता है और आप बेस क्लास या एब्सट्रैक्ट बेस क्लास का उपयोग करना चाहेंगे।
अमूर्त कक्षाएं वे कक्षाएं होती हैं जिनमें एक या एक से अधिक सार विधियां होती हैं। अमूर्त विधियों के साथ, सार वर्गों में स्थिर, वर्ग और उदाहरण विधियां हो सकती हैं। लेकिन इंटरफ़ेस के मामले में, इसमें केवल अमूर्त विधियाँ होंगी अन्य नहीं। इसलिए यह अमूर्त वर्ग को विरासत में लेने के लिए अनिवार्य नहीं है, लेकिन इनहेरिट इंटरफ़ेस के लिए अनिवार्य है।
पूर्णता के लिए, हमें PEP3119 का उल्लेख करना चाहिए जहां एबीसी को इंटरफेस के साथ पेश किया गया था और मूल तालिन की टिप्पणी के साथ तुलना की गई थी ।
सार वर्ग सही इंटरफ़ेस नहीं है:
लेकिन अगर आप इसे अपने तरीके से लिखने पर विचार करते हैं:
def some_function(self):
raise NotImplementedError()
interface = type(
'your_interface', (object,),
{'extra_func': some_function,
'__slots__': ['extra_func', ...]
...
'__instancecheck__': your_instance_checker,
'__subclasscheck__': your_subclass_checker
...
}
)
ok, rather as a class
or as a metaclass
and fighting with python to achieve the immutable object
and doing refactoring
...
आप काफी तेजी से महसूस करेंगे कि आप अंततः प्राप्त करने के लिए पहिया का आविष्कार कर रहे हैं
abc.ABCMeta
abc.ABCMeta
लापता इंटरफ़ेस कार्यक्षमता के एक उपयोगी जोड़ के रूप में प्रस्तावित किया गया था, और यह अजगर की तरह एक भाषा में पर्याप्त उचित है।
निश्चित रूप से, यह संस्करण 3 को लिखते समय और नए सिंटैक्स और अपरिवर्तनीय इंटरफ़ेस अवधारणा को जोड़ते हुए बेहतर तरीके से बढ़ाया जा सकता था ...
निष्कर्ष:
The abc.ABCMeta IS "pythonic" interface in python