2010-03-26 14 views
32

मैंने अपने कोड में ज़ोप इंटरफेस का उपयोग करना शुरू कर दिया है, और अभी तक, वे वास्तव में केवल दस्तावेज़ीकरण हैं। मैं उनका उपयोग यह निर्दिष्ट करने के लिए करता हूं कि कक्षा के गुणों का क्या होना चाहिए, स्पष्ट रूप से उचित कक्षाओं में उन्हें लागू करें और स्पष्ट रूप से उन लोगों की जांच करें जहां मैं एक की अपेक्षा करता हूं। यह ठीक है, लेकिन यदि संभव हो तो मैं उन्हें और अधिक करना चाहूंगा, जैसे कि वास्तव में सत्यापित करें कि कक्षा ने इंटरफ़ेस को कार्यान्वित किया है, केवल यह सत्यापित करने के बजाय कि मैंने कहा है कि कक्षा इंटरफ़ेस लागू करती है। मैंने ज़ोप विकी को दो बार पढ़ा है, लेकिन अभी भी मैं जो कर रहा हूं उससे इंटरफेस के लिए और अधिक उपयोग नहीं देख सकता। तो, मेरा सवाल यह है कि आप इन इंटरफेस का और क्या उपयोग कर सकते हैं, और आप उन्हें और अधिक के लिए कैसे उपयोग करते हैं।ज़ोप इंटरफेस का उद्देश्य?

उत्तर

23

आप वास्तव में परीक्षण कर सकते हैं कि आपका ऑब्जेक्ट या क्लास आपके इंटरफ़ेस को लागू करता है या नहीं। कि आप verify मॉड्यूल का उपयोग कर सकते हैं (आप सामान्य रूप से अपने परीक्षण में यह प्रयोग करेंगे):

>>> from zope.interface import Interface, Attribute, implements 
>>> class IFoo(Interface): 
...  x = Attribute("The X attribute") 
...  y = Attribute("The Y attribute") 

>>> class Foo(object): 
...  implements(IFoo) 
...  x = 1 
...  def __init__(self): 
...   self.y = 2 

>>> from zope.interface.verify import verifyObject 
>>> verifyObject(IFoo, Foo()) 
True 

>>> from zope.interface.verify import verifyClass 
>>> verifyClass(IFoo, Foo) 
True 

इंटरफेस भी स्थापित करने और अपरिवर्तनशीलताओं के परीक्षण के लिए इस्तेमाल किया जा सकता। आप यहाँ अधिक जानकारी प्राप्त कर सकते हैं:

http://www.muthukadan.net/docs/zca.html#interfaces

+2

कूल, अनुमान लगाएं कि आपके स्वयं के परीक्षण लिखने का मेरा समाधान अनावश्यक है। हालांकि परीक्षण परीक्षण पर भरोसा करने के बजाए यह अभी भी रनटाइम अपवादों के लिए उपयोगी हो सकता है, यह एक बेहतर समाधान है। –

+0

धन्यवाद, यह वही है जो मैं ढूंढ रहा था। मुझे यकीन था कि ऐसा करने का कोई तरीका था, लेकिन मुझे नहीं पता था कि कैसे। – Nikwin

+1

इसके अलावा, ज़ोप देखें।स्कीमा- यह प्रकार निर्दिष्ट करने के लिए एक और विस्तृत तरीका प्रदान करता है। और zope.interface.invariant भी है जिसका उपयोग इंटरफ़ेस प्रदान करने वाले वास्तविक आविष्कार वस्तुओं को परिभाषित करने के लिए किया जा सकता है। पूर्णता के लिए –

2

मैंने ज़ोप इंटरफेस का कभी भी उपयोग नहीं किया है, लेकिन आप metaclass लिखने पर विचार कर सकते हैं, जो प्रारंभिक पर कक्षा के सदस्यों को इंटरफ़ेस के खिलाफ जांचता है, और एक विधि लागू नहीं होने पर रनटाइम अपवाद उठाता है।

पायथन के साथ आपके पास अन्य विकल्प नहीं हैं। या तो एक "संकलन" चरण है जो आपके कोड का निरीक्षण करता है, या रनटाइम पर गतिशील रूप से इसका निरीक्षण करता है।

19

Zope इंटरफेस कोड के दो टुकड़े कि एक दूसरे पर निर्भर नहीं करना चाहिए दसगुणा एक उपयोगी तरीका प्रदान कर सकते हैं।

कहते हैं कि हम एक घटक जानता है कि कैसे मॉड्यूल a.py में एक ग्रीटिंग मुद्रित करने के लिए है:

>>> class Greeter(object): 
...  def greet(self): 
...   print 'Hello' 

और कुछ कोड मॉड्यूल b.py में एक ग्रीटिंग मुद्रित करने के लिए की जरूरत है:

>>> Greeter().greet() 
'Hello' 

यह व्यवस्था उस कोड को स्वैप करना मुश्किल बनाती है जो b.py को छूए बिना ग्रीटिंग को नियंत्रित करती है (जिसे एक अलग पैकेज में वितरित किया जा सकता है)।

>>> from zope.interface import Interface 
>>> class IGreeter(Interface): 
...  def greet(): 
...   """ Gives a greeting. """ 

अब हम इस का उपयोग कर सकते a.py और b.py. दसगुणा: इसके बजाय, हम एक तिहाई मॉड्यूल c.py जो एक IGreeter इंटरफेस को परिभाषित करता दे सकते हैं एक ग्रीटर वर्ग को तुरंत चालू करने के बजाय, b.py अब आईजीरेटर इंटरफ़ेस प्रदान करने वाली उपयोगिता मांगेगा। और a.py घोषणा करेंगे कि स्वागतकर्ता वर्ग है कि इंटरफ़ेस लागू करता है:

(a.py) 
>>> from zope.interface import implementer 
>>> from zope.component import provideUtility 
>>> from c import IGreeter 

>>> @implementer(IGreeter) 
... class Greeter(object): 
...  def greet(self): 
...   print 'Hello' 
>>> provideUtility(Greeter(), IGreeter) 

(b.py) 
>>> from zope.component import getUtility 
>>> from c import IGreeter 

>>> greeter = getUtility(IGreeter) 
>>> greeter.greet() 
'Hello' 
+1

, क्या आप एडाप्टर के लिए एक उदाहरण जोड़ सकते हैं? – sureshvv

+0

'ग्रीटिंग को संभालने वाले कोड को स्वैप करें' से आपका क्या मतलब है? जैसा कि आपने उपरोक्त दिखाया है, इंटरफ़ेस का उपयोग करके यह समस्या हल हो जाती है? –

+1

'b.py' में वह एक परेशान हो रहा है लेकिन उसने' ए' आयात नहीं किया है। यानी: आयात ग्रिटर ' – Kurt

47

मैं कहां से काम करते हैं, हम इंटरफेस का उपयोग करें ताकि हम ZCA, या Zope Component Architecture, जो घटक है कि swappable हैं बनाने के लिए एक पूरी रूपरेखा है उपयोग कर सकते हैं और Interface एस का उपयोग कर प्लग करने योग्य। हम जेडसीए का उपयोग करते हैं ताकि हम अपने सॉफ़्टवेयर को फोर्क करने के बिना सभी प्रकार के प्रति-ग्राहक अनुकूलन का सामना कर सकें या मुख्य पेड़ को गड़बड़ कर रहे कई सारे क्लाइंट बिट्स प्राप्त कर सकें। दुर्भाग्यवश, ज़ोप विकी अक्सर अधूरा है। इसके ZCA's pypi page पर जेडसीए की अधिकांश सुविधाओं का एक अच्छा-लेकिन-वर्णन स्पष्टीकरण है।

मैं किसी भी Interface के लिए सभी विधियों को लागू करने की जांच करने के लिए Interface एस का उपयोग नहीं करता हूं।सिद्धांत रूप में, यह तब उपयोगी हो सकता है जब आप किसी इंटरफ़ेस को एक और तरीका जोड़ते हैं, यह जांचने के लिए कि आपने इंटरफ़ेस को लागू करने वाले सभी वर्गों में नई विधि जोड़ने के लिए याद किया है। व्यक्तिगत रूप से मैं दृढ़ता से एक नया संशोधित करने पर एक नया Interface बनाना पसंद करता हूं। पुराने Interfaces को संशोधित करना आमतौर पर एक बहुत बुरा विचार होता है जब वे अंडे में होते हैं जिन्हें पीपीआई या आपके बाकी संगठन में छोड़ दिया जाता है।

शब्दावली पर एक त्वरित नोट: कक्षाएं लागूInterface है, और वस्तुओं (वर्गों के उदाहरण) प्रदानInterface रों। यदि आप Interface की जांच करना चाहते हैं, तो आप या तो ISomething.implementedBy(SomeClass) या ISomething.providedBy(some_object) लिखेंगे।

तो, जहां जेडसीए उपयोगी है, उदाहरणों के लिए नीचे। आइए दिखाएं कि हम इसे मॉड्यूलर बनाने के लिए जेडसीए का उपयोग करके एक ब्लॉग लिख रहे हैं। हमारे पास प्रत्येक पोस्ट के लिए BlogPost ऑब्जेक्ट होगा, जो IBlogPost इंटरफ़ेस प्रदान करेगा, जो हमारे सुविधाजनक-डेन्डी my.blog अंडे में परिभाषित हैं। हम ब्लॉग की कॉन्फ़िगरेशन को BlogConfiguration ऑब्जेक्ट्स में भी स्टोर करेंगे जो IBlogConfiguration प्रदान करते हैं। इसे शुरुआती बिंदु के रूप में उपयोग करते हुए, हम my.blog को स्पर्श करने के बिना आवश्यक नई सुविधाओं को लागू कर सकते हैं।

निम्नलिखित my.blog अंडे को बदलने के बिना, ZCA का उपयोग करके हम उन चीजों के उदाहरणों की एक सूची है जो हम कर सकते हैं। वास्तविक या क्लाइंट परियोजनाओं पर मैंने या मेरे सहकर्मियों ने इन सभी चीजों को (और उन्हें उपयोगी पाया) किया है, हालांकि हम उस समय ब्लॉग को लागू नहीं कर रहे थे। :) यहां कुछ उपयोग मामलों को बेहतर तरीके से हल किया जा सकता है, जैसे एक प्रिंट सीएसएस फ़ाइल।

  1. सभी वस्तुओं जो IBlogPost प्रदान करने के लिए अतिरिक्त दृश्य (BrowserView है, आम तौर पर browser:page निर्देश के साथ ZCML में पंजीकृत) जोड़ना। मैं my.blog.printable अंडा बना सकता था। वह अंडे print नामक ब्राउज़र ब्राउज़र को IBlogPost के लिए पंजीकृत करेगा, जो Zope Page Template के माध्यम से ब्लॉग पोस्ट को प्रस्तुत करता है जो एचटीएमएल का उत्पादन करने के लिए डिज़ाइन किया गया है जो अच्छी तरह से प्रिंट करता है। तब BrowserView यूआरएल /path/to/blogpost/@@print पर दिखाई देगा।

  2. ज़ोप में ईवेंट सदस्यता तंत्र। मान लें कि मैं आरएसएस फ़ीड प्रकाशित करना चाहता हूं, और मैं अनुरोध के बजाय उन्हें अग्रिम में उत्पन्न करना चाहता हूं। मैं my.blog.rss अंडा बना सकता था। उस अंडे में, मैं प्रदान करने वाली वस्तुओं पर IObjectModified (zope.lifecycleevent.interfaces.IObjectModified) प्रदान करने वाली घटनाओं के लिए एक ग्राहक पंजीकृत करता हूं। उस ग्राहक को IBlogPost प्रदान करने वाली किसी भी चीज़ पर एक विशेषता बदलने के लिए बुलाया जाएगा, और मैं ब्लॉग आरएसएस फ़ीड में सभी आरएसएस फ़ीड अपडेट करने के लिए इसका उपयोग कर सकता हूं।

    इस मामले में, यह बेहतर हो सकता है कि यह बेहतर हो IBlogPostModified ईवेंट BrowserView एस के अंत में भेजा गया है जो ब्लॉग पोस्ट को संशोधित करता है, क्योंकि IObjectModified प्रत्येक एकल विशेषता परिवर्तन पर एक बार भेजा जाता है - जो प्रदर्शन के लिए अक्सर हो सकता है।

  3. एडाप्टर। एडाप्टर प्रभावी रूप से एक इंटरफ़ेस से दूसरे में "कास्ट" होते हैं। प्रोग्रामिंग भाषा गीक्स के लिए: ज़ोपे एडाप्टर पाइथन में "ओपन" एकाधिक-प्रेषण को लागू करते हैं ("ओपन" से मेरा मतलब है "आप किसी भी अंडे से अधिक मामले जोड़ सकते हैं"), कम-विशिष्ट इंटरफ़ेस मिलान कम-विशिष्ट मैचों पर प्राथमिकता लेते हैं (Interface कक्षाएं एक दूसरे के उपवर्गों हो सकता है, और यह करता है आप आशा है कि यह करना होगा चाहते हैं कि वास्तव में क्या।)

    एक Interface से

    एडेप्टर, एक बहुत अच्छा वाक्य रचना के साथ कहा जा सकता है ISomething(object_to_adapt), या समारोह zope.component.getAdapter के माध्यम से देखा जा सकता है ।एकाधिक Interface से एडाप्टर को zope.component.getMultiAdapter फ़ंक्शन के माध्यम से देखा जाना चाहिए, जो थोड़ा कम सुंदर है।

    आपके पास Interface एस के दिए गए सेट के लिए एक से अधिक एडाप्टर हो सकते हैं, जो एक स्ट्रिंग name द्वारा अलग किया गया है जो आप एडाप्टर को पंजीकृत करते समय प्रदान करते हैं। नाम "" पर डिफ़ॉल्ट है। उदाहरण के लिए, BrowserView एस वास्तव में ऐसे एडाप्टर हैं जो इंटरफ़ेस से अनुकूलित होते हैं और वे एक इंटरफ़ेस जो HTTPRequest क्लास लागू करता है। आप को Interface एस के एक अनुक्रम से पंजीकृत पर zope.component.getAdapters((IAdaptFrom,), IAdaptTo) का उपयोग करके देख सकते हैं, जो कि (नाम, एडाप्टर) जोड़े का अनुक्रम देता है। यह प्लगइन के लिए खुद को संलग्न करने के लिए हुक प्रदान करने के लिए एक बहुत अच्छा तरीका के रूप में उपयोग किया जा सकता है।

    कहें कि मैं अपने सभी ब्लॉग की पोस्ट और कॉन्फ़िगरेशन को एक बड़ी एक्सएमएल फ़ाइल के रूप में सहेजना चाहता हूं। मैं my.blog.xmldump अंडा बना देता हूं जो IXMLSegment को परिभाषित करता है, और IBlogPost से IXMLSegment और IBlogConfiguration से IXMLSegment पर एडाप्टर पंजीकृत करता है। अब मैं किसी भी ऑब्जेक्ट के लिए जो भी एडाप्टर उपयुक्त है उसे कॉल कर सकता हूं जिसे मैं IXMLSegment(object_to_serialize) लिखकर क्रमबद्ध करना चाहता हूं।

    मैं और भी अधिक एडेप्टर विभिन्न अन्य चीजों से IXMLSegment करने के लिए my.blog.xmldump के अलावा अन्य अंडे से जोड़ सकते हैं। जेडसीएमएल में एक सुविधा है जहां यह एक विशेष निर्देश चला सकता है अगर केवल कुछ अंडा स्थापित हो। मैं इसका उपयोग my.blog.rssIRSSFeed से IXMLSegment iff my.blog.xmldump स्थापित करने के लिए होता है, my.blog.rssmy.blog.xmldump पर निर्भर किए बिना एक एडाप्टर पंजीकृत कर सकता है।

  4. Viewlet एस BrowserView की तरह हैं कि आप किसी पृष्ठ के अंदर किसी विशेष स्थान पर 'सब्सक्राइब' कर सकते हैं। मुझे अभी सभी विवरण याद नहीं हैं लेकिन प्लगइन जैसी चीजों के लिए ये बहुत अच्छे हैं जिन्हें आप साइडबार में दिखाना चाहते हैं।

    मुझे याद नहीं है कि वे आधार ज़ोप या प्लोन का हिस्सा हैं या नहीं। मैं प्लोन का उपयोग करने के खिलाफ अनुशंसा करता हूं जब तक कि आप जिस समस्या को हल करने की कोशिश कर रहे हैं, वास्तव में वास्तविक सीएमएस की आवश्यकता नहीं है, क्योंकि यह सॉफ़्टवेयर का एक बड़ा और जटिल टुकड़ा है और यह थोड़ी धीमी गति से पड़ता है।

    आप जरूरी वास्तव में Viewlet रों वैसे भी, की जरूरत नहीं है के बाद से BrowserView है, या तो एक TAL अभिव्यक्ति में 'वस्तु/@@ some_browser_view' का उपयोग करके एक-दूसरे को कॉल कर सकते हैं, या queryMultiAdapter((ISomething, IHttpRequest), name='some_browser_view') का उपयोग करके, लेकिन वे परवाह किए बिना बहुत अच्छा कर रहे हैं ।

  5. मार्कर Interface एस। एक मार्कर Interface एक Interface है जो कोई विधियां और कोई विशेषता नहीं प्रदान करता है। आप ISomething.alsoProvidedBy का उपयोग कर रनटाइम पर किसी भी ऑब्जेक्ट को मार्कर Interface जोड़ सकते हैं। यह आपको उदाहरण के लिए, एक विशेष ऑब्जेक्ट पर कौन से एडाप्टर का उपयोग करेगा, और BrowserView एस पर परिभाषित किया जाएगा, इसे बदलने की अनुमति देता है।

मैं माफी माँगता हूँ कि मैं इन उदाहरणों में से प्रत्येक सीधे लागू करने के लिए सक्षम होने के लिए पर्याप्त विस्तार में नहीं गए, लेकिन वे लगभग एक ब्लॉग पोस्ट प्रत्येक काफ़ी होगा।

+1

महान स्पष्टीकरण, इसके लिए धन्यवाद! –

+2

+1 - यह वास्तव में एक शर्म की बात है कि बहुत से लोगों को पता नहीं है कि एडेप्टर वास्तव में एकाधिक प्रेषण/multimethods का एक तंत्र है। अच्छे उदाहरण के लिए –

+0

+1 और जो भी 40-50% उत्तर मैं समझने में सक्षम था। इतनी नई शब्दावली। –

संबंधित मुद्दे