हाय, हैब्र। हाल ही में मैं डिजाइन - एक्सेस मॉडिफायर और इंटरफेस के बारे में पागल हो गया, फिर मैंने इसे पायथन प्रोग्रामिंग भाषा में पोर्ट किया। मैं कैट के तहत पूछता हूं - मैं परिणाम साझा करता हूं और यह कैसे काम करता है। रुचि रखने वालों के लिए, लेख के अंत में गितुब पर परियोजना की एक कड़ी है।
पहुँच संशोधक
एक्सेस संशोधक वस्तुओं तक पहुंच को सीमित करते हैं - उनकी कक्षा के तरीकों को, या बाल कक्षाओं को - उनके मूल वर्ग के तरीकों को। एक्सेस मॉडिफ़ायर का उपयोग कक्षा में डेटा को छिपाने में मदद करता है ताकि कोई भी बाहर इस वर्ग के काम में हस्तक्षेप न कर सके।
निजी विधियाँ केवल कक्षा के अंदर,
संरक्षित (अंदर) - कक्षा के अंदर और बाल कक्षाओं में उपलब्ध हैं।
पायथन में निजी और संरक्षित तरीके कैसे लागू होते हैं
स्पॉयलर - समझौते के स्तर पर कि वयस्क उन्हें कक्षा के बाहर नहीं बुलाएंगे। निजी तरीकों से पहले, आपको संरक्षित होने से पहले एक डबल अंडरस्कोर लिखना होगा। और आप "सीमित" पहुंच के बावजूद भी तरीकों का उपयोग कर सकते हैं।
class Car: def _start_engine(self): return "Engine's sound." def run(self): return self._start_engine() if __name__ == '__main__': car = Car() assert "Engine's sound." == car.run() assert "Engine's sound." == car._start_engine()
निम्नलिखित नुकसान निर्धारित किए जा सकते हैं:
- यदि _start_engine विधि ने कुछ वर्ग चर या राज्य को अपडेट किया है, और न केवल " डंब गणना" लौटा दी है, तो आप वर्ग के साथ भविष्य के काम के लिए कुछ तोड़ सकते हैं। आप अपने आप को अपनी कार के इंजन में कुछ मरम्मत करने की अनुमति नहीं देते हैं, क्योंकि तब आप कहीं भी नहीं जाते हैं, है ना?
- पिछले एक से बहने वाला बिंदु - यह सुनिश्चित करने के लिए कि आप "सुरक्षित रूप से" कर सकते हैं (कॉलिंग विधि खुद को वर्ग को नुकसान नहीं पहुंचाती है) एक संरक्षित विधि का उपयोग करें - आपको इसके कोड को देखने और समय बिताने की आवश्यकता है।
- पुस्तकालयों के लेखक उम्मीद करते हैं कि कोई भी उन परियोजनाओं के संरक्षित और निजी तरीकों का उपयोग नहीं करता है जो आप अपनी परियोजनाओं में उपयोग करते हैं। इसलिए, वे किसी भी रिलीज में इसके कार्यान्वयन को बदल सकते हैं (जो पिछड़े संगतता के कारण सार्वजनिक तरीकों को प्रभावित नहीं करेगा, लेकिन आपको नुकसान होगा)।
- कक्षा के लेखक, आपके सहकर्मी, यह अपेक्षा करते हैं कि आपके द्वारा बनाई गई कक्षा के बाहर संरक्षित या निजी पद्धति का उपयोग करके आप परियोजना के तकनीकी ऋण में वृद्धि नहीं करेंगे। आखिरकार, जो इसे (निजी वर्ग विधि) को संशोधित या संशोधित करेगा, उसे यह सुनिश्चित करना होगा (उदाहरण के लिए, परीक्षणों के माध्यम से) कि उसके परिवर्तन आपके कोड को नहीं तोड़ेंगे। और अगर वे इसे तोड़ते हैं, तो उन्हें इस समस्या को हल करने के लिए समय बिताना होगा (एक बैसाखी के साथ, क्योंकि उसे कल इसकी आवश्यकता है)।
- शायद आप यह सुनिश्चित करते हैं कि अन्य प्रोग्रामर कोड समीक्षा और "इसके लिए हरा" पर संरक्षित या निजी तरीकों का उपयोग नहीं करते हैं, इसलिए समय व्यतीत करें।
पुस्तकालय का उपयोग करके संरक्षित विधियों को कैसे लागू किया जाए
from accessify import protected class Car: @protected def start_engine(self): return "Engine's sound." def run(self): return self.start_engine() if __name__ == '__main__': car = Car() assert "Engine's sound." == car.run() car.start_engine()
कक्षा के बाहर
start_engine पद्धति को कॉल करने का प्रयास करने के परिणामस्वरूप निम्न त्रुटि होगी (एक्सेस नीति के अनुसार विधि उपलब्ध नहीं है):
Traceback (most recent call last): File "examples/access/private.py", line 24, in <module> car.start_engine() File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/accessify/main.py", line 92, in private_wrapper class_name=instance_class.__name__, method_name=method.__name__, accessify.errors.InaccessibleDueToItsProtectionLevelException: Car.start_engine() is inaccessible due to its protection level
पुस्तकालय का उपयोग करना:
- आपको बदसूरत (व्यक्तिपरक) अंडरस्कोर या डबल अंडरस्कोर का उपयोग करने की आवश्यकता नहीं है।
- कोड में एक्सेस मॉडिफायर लागू करने के लिए आपको एक सुंदर (व्यक्तिपरक) तरीका मिलता है - निजी और संरक्षित सज्जाकार।
- दुभाषिया से व्यक्ति की जिम्मेदारी हस्तांतरित करें।
यह कैसे काम करता है:
- निजी या संरक्षित डेकोरेटर - सबसे "उच्च" डेकोरेटर, क्लास विधि से पहले फायर करता है , जिसे एक निजी या संरक्षित एक्सेस संशोधक घोषित किया गया था।
- बिल्ट-इन इंस्पेक्ट लाइब्रेरी का उपयोग करते हुए, डेकोरेटर कॉल स्टैक से वर्तमान ऑब्जेक्ट को पुनः प्राप्त करता है - निरीक्षण.क्रिकेटफ्रेम () । इस ऑब्जेक्ट में निम्नलिखित विशेषताएं हैं जो हमारे लिए उपयोगी हैं: नाम स्थान (स्थानीय) और कॉल स्टैक से पिछले ऑब्जेक्ट के लिए लिंक (एक्सेस मॉडिफायर के साथ विधि को कॉल करने वाली वस्तु)।
(बहुत सरल चित्रण)
- निरीक्षण करें। currentframe ()। f_back - इस विशेषता का उपयोग यह जांचने के लिए करें कि कॉल स्टैक से पिछला ऑब्जेक्ट क्लास बॉडी में है या नहीं। ऐसा करने के लिए, नामस्थान - f_locals को देखें । यदि नाम स्थान में एक स्व विशेषता है, तो विधि को कक्षा के अंदर कहा जाता है, यदि नहीं, तो कक्षा के बाहर। यदि आप कक्षा के बाहर एक निजी या संरक्षित एक्सेस संशोधक के साथ एक विधि कहते हैं, तो एक एक्सेस पॉलिसी त्रुटि होगी।
इंटरफेस
इंटरफेस एक वर्ग के साथ बातचीत का एक अनुबंध है जो इसे लागू करता है। इंटरफ़ेस में विधि हस्ताक्षर (फ़ंक्शन का नाम, इनपुट तर्क) शामिल हैं, और वर्ग जो इंटरफ़ेस को लागू करता है, हस्ताक्षर के बाद, तर्क को लागू करता है। सारांशित करते हुए, यदि दो वर्ग समान इंटरफ़ेस लागू करते हैं, तो आप यह सुनिश्चित कर सकते हैं कि इन वर्गों की दोनों वस्तुओं में समान विधियाँ हैं।
उदाहरण
हमारे पास एक
उपयोगकर्ता वर्ग है जो एक नया उपयोगकर्ता बनाने के लिए
स्टोरेज ऑब्जेक्ट का उपयोग करता है।
class User: def __init__(self, storage): self.storage = storage def create(self, name): return storage.create_with_name(name=name)
आप डेटाबेस को डेटाबेस में उपयोग करके डेटाबेस को बचा सकते हैं।
class DatabaseStorage: def create_with_name(self, name): ...
आप
FileStorage.create_with_name का उपयोग करके फ़ाइलों को सहेज सकते हैं।
class FileStorage: def create_with_name(self, name): ...
इस तथ्य के कारण कि
create_with_name विधियों (नाम, तर्क) के हस्ताक्षर कक्षाओं के लिए समान हैं -
उपयोगकर्ता वर्ग को इस बारे में चिंता करने की आवश्यकता नहीं है कि दोनों किस समान विधियों के लिए किस ऑब्जेक्ट को प्रतिस्थापित किया गया था। यह प्राप्त किया जा सकता है यदि
फ़ाइलस्टोरेज और
डेटाबेसस्टोरेज कक्षाएं एक ही इंटरफ़ेस को लागू करती हैं (अर्थात, वे अनुबंध के अंदर तर्क के साथ कुछ विधि को परिभाषित करने के लिए बाध्य हैं)।
if __name__ == '__main__': if settings.config.storage = FileStorage: storage = FileStorage() if settings.config.storage = DatabaseStorage: storage = DatabaseStorage() user = User(storage=storage) user.create_with_name(name=...)
लाइब्रेरी का उपयोग करके इंटरफेस के साथ कैसे काम करें
यदि कोई वर्ग इंटरफ़ेस को लागू करता है, तो कक्षा
में इंटरफ़ेस के सभी तरीके होने चाहिए। नीचे दिए गए उदाहरण में, HumanInterface इंटरफ़ेस में खाने की विधि है, और मानव वर्ग इसे लागू करता है, लेकिन खाने की विधि को लागू नहीं करता है।
from accessify import implements class HumanInterface: @staticmethod def eat(food, *args, allergy=None, **kwargs): pass if __name__ == '__main__': @implements(HumanInterface) class Human: pass
स्क्रिप्ट निम्न त्रुटि से बाहर निकलेगी:
Traceback (most recent call last): File "examples/interfaces/single.py", line 18, in <module> @implements(HumanInterface) File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/accessify/interfaces.py", line 66, in decorator interface_method_arguments=interface_method.arguments_as_string, accessify.errors.InterfaceMemberHasNotBeenImplementedException: class Human does not implement interface member HumanInterface.eat(food, args, allergy, kwargs)
यदि कोई वर्ग इंटरफ़ेस को लागू करता है, तो कक्षा
में सभी आवक तर्कों सहित इंटरफ़ेस की सभी विधियाँ होनी चाहिए। नीचे दिए गए उदाहरण में, HumanInterface इंटरफ़ेस में खाने की विधि है, जो इनपुट के लिए 4 तर्क लेता है, और मानव वर्ग इसे लागू करता है, लेकिन केवल 1 तर्क के साथ खाने की विधि को लागू करता है।
from accessify import implements class HumanInterface: @staticmethod def eat(food, *args, allergy=None, **kwargs): pass if __name__ == '__main__': @implements(HumanInterface) class Human: @staticmethod def eat(food): pass
स्क्रिप्ट निम्न त्रुटि से बाहर निकलेगी:
Traceback (most recent call last): File "examples/interfaces/single_arguments.py", line 16, in <module> @implements(HumanInterface) File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/accessify/interfaces.py", line 87, in decorator interface_method_arguments=interface_method.arguments_as_string, accessify.errors.InterfaceMemberHasNotBeenImplementedWithMismatchedArgumentsException: class Human implements interface member HumanInterface.eat(food, args, allergy, kwargs) with mismatched arguments
यदि कोई वर्ग इंटरफ़ेस लागू करता है, तो कक्षा में इंटरफ़ेस के सभी तरीके शामिल होने चाहिए, जिसमें इनकमिंग तर्क और
एक्सेस मॉडिफायर शामिल हैं । नीचे दिए गए उदाहरण में, HumanInterface इंटरफ़ेस में निजी खाने की विधि है, और मानव वर्ग इसे लागू करता है, लेकिन खाने के तरीके के लिए निजी एक्सेस संशोधक को लागू नहीं करता है।
from accessify import implements, private class HumanInterface: @private @staticmethod def eat(food, *args, allergy=None, **kwargs): pass if __name__ == '__main__': @implements(HumanInterface) class Human: @staticmethod def eat(food, *args, allergy=None, **kwargs): pass
स्क्रिप्ट निम्न त्रुटि से बाहर निकलेगी:
Traceback (most recent call last): File "examples/interfaces/single_access.py", line 18, in <module> @implements(HumanInterface) File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/accessify/interfaces.py", line 77, in decorator interface_method_name=interface_method.name, accessify.errors.ImplementedInterfaceMemberHasIncorrectAccessModifierException: Human.eat(food, args, allergy, kwargs) mismatches HumanInterface.eat() member access modifier.
एक वर्ग कई (असीमित संख्या में) इंटरफेस को लागू कर सकता है। यदि कोई वर्ग कई इंटरफेस को लागू करता है, तो कक्षा
में आने वाले तर्कों और एक्सेस संशोधक सहित सभी इंटरफेस के सभी तरीके शामिल होने चाहिए। नीचे दिए गए उदाहरण में, मानव वर्ग HumanBasicsInterface इंटरफ़ेस की खाने की विधि को लागू करता है, लेकिन HumanSoulInterface इंटरफ़ेस की प्रेम पद्धति को लागू नहीं करता है।
from accessify import implements class HumanSoulInterface: def love(self, who, *args, **kwargs): pass class HumanBasicsInterface: @staticmethod def eat(food, *args, allergy=None, **kwargs): pass if __name__ == '__main__': @implements(HumanSoulInterface, HumanBasicsInterface) class Human: def love(self, who, *args, **kwargs): pass
स्क्रिप्ट निम्न त्रुटि से बाहर निकलेगी:
Traceback (most recent call last): File "examples/interfaces/multiple.py", line 19, in <module> @implements(HumanSoulInterface, HumanBasicsInterface) File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/accessify/interfaces.py", line 66, in decorator interface_method_arguments=interface_method.arguments_as_string, accessify.errors.InterfaceMemberHasNotBeenImplementedException: class Human does not implement interface member HumanBasicsInterface.eat(food, args, allergy, kwargs)
किलर फीचर - एक इंटरफ़ेस विधि "राज्य" कर सकती है कि एक वर्ग की एक विधि क्या त्रुटियों को लागू करती है जो इसे "फेंकना" चाहिए। नीचे दिए गए उदाहरण में, यह "घोषित किया गया" है कि "ह्यूमनइंटरफेस" इंटरफ़ेस के "प्यार" विधि को "ह्यूमनडॉइट्सनोटिस्टस्ट्रीम" अपवाद और फेंक देना चाहिए
"HumanAlreadyInLoveError", लेकिन "मानव" वर्ग का "प्यार" विधि उनमें से एक को "फेंक" नहीं करता है।
from accessify import implements, throws class HumanDoesNotExistError(Exception): pass class HumanAlreadyInLoveError(Exception): pass class HumanInterface: @throws(HumanDoesNotExistError, HumanAlreadyInLoveError) def love(self, who, *args, **kwargs): pass if __name__ == '__main__': @implements(HumanInterface) class Human: def love(self, who, *args, **kwargs): if who is None: raise HumanDoesNotExistError('Human whom need to love does not exist')
स्क्रिप्ट निम्न त्रुटि से बाहर निकलेगी:
Traceback (most recent call last): File "examples/interfaces/throws.py", line 21, in <module> @implements(HumanInterface) File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/accessify/interfaces.py", line 103, in decorator class_method_arguments=class_member.arguments_as_string, accessify.errors.DeclaredInterfaceExceptionHasNotBeenImplementedException: Declared exception HumanAlreadyInLoveError by HumanInterface.love() member has not been implemented by Human.love(self, who, args, kwargs)
संक्षेप में, पुस्तकालय का उपयोग करने के लिए:
- आप एक या अधिक इंटरफेस लागू कर सकते हैं।
- इंटरफेसेस एक्सेस मॉडिफायर्स के साथ संयुक्त हैं।
- आपको इंटरफेस और एब्स्ट्रैक्ट क्लासेस ( Python में एबीसी मॉड्यूल ) का पृथक्करण मिलेगा, अब आपको एब्सट्रैक्ट क्लासेस को इंटरफेस के रूप में उपयोग करने की आवश्यकता नहीं है यदि आपने (मैंने किया था)।
- अमूर्त वर्गों की तुलना में। यदि आपने इंटरफ़ेस से विधि के सभी तर्कों को परिभाषित नहीं किया है, तो आपको एक अमूर्त वर्ग का उपयोग करके एक त्रुटि मिलेगी - नहीं।
- अमूर्त वर्गों की तुलना में। इंटरफेस का उपयोग करते हुए, आपको कक्षा बनाते समय एक त्रुटि मिलेगी (जब आपने कक्षा को लिखा और * .py फ़ाइल कहा जाता है)। अमूर्त कक्षाओं में, आपको क्लास ऑब्जेक्ट की एक विधि को कॉल करने के चरण में पहले से ही एक त्रुटि मिलेगी।
यह कैसे काम करता है:
- इम्प्लीमेंट्स डेकोरेटर में बिल्ट-इन इंस्पेक्ट लाइब्रेरी का उपयोग करते हुए, क्लास के सभी तरीकों और इसके इंटरफेस - इंस्पेक्ट.गेटमबर्स () को प्राप्त किया जाता है । एक विधि का एक अनोखा सूचकांक इसके नाम और प्रकार (स्टेटमिथोड, संपत्ति, और इसी तरह) का एक संयोजन है।
- और निरीक्षण के साथ। संकेत () , विधि के तर्क।
- हम इंटरफ़ेस के सभी तरीकों के माध्यम से लूप करते हैं, और देखते हैं कि क्या क्लास में ऐसी कोई विधि (किसी अद्वितीय अनुक्रमणिका द्वारा) है जो इंटरफ़ेस को लागू करता है, चाहे आने वाले तर्क समान हों, चाहे एक्सेस मॉडिफ़ायर समान हों, चाहे वह विधि इंटरफ़ेस की विधि में घोषित त्रुटियों को लागू करती हो।
लेख पर ध्यान देने के लिए आपका धन्यवाद।
गिथब पर परियोजना के लिए लिंक ।