मैं यह समझने की कोशिश कर रहा हूं कि बंदर का पेटिंग या बंदर का पैच क्या है?
क्या कुछ ऐसा है जैसे कि तरीके / ऑपरेटर ओवरलोडिंग या डेलिगेटिंग हैं?
क्या यह इन चीजों के साथ कुछ सामान्य है?
मैं यह समझने की कोशिश कर रहा हूं कि बंदर का पेटिंग या बंदर का पैच क्या है?
क्या कुछ ऐसा है जैसे कि तरीके / ऑपरेटर ओवरलोडिंग या डेलिगेटिंग हैं?
क्या यह इन चीजों के साथ कुछ सामान्य है?
जवाबों:
नहीं, यह उन चीजों में से किसी की तरह नहीं है। यह बस रनटाइम पर विशेषताओं का गतिशील प्रतिस्थापन है।
उदाहरण के लिए, एक विधि पर विचार करें get_data
। यह विधि एक बाहरी लुकअप (डेटाबेस या वेब एपीआई पर, उदाहरण के लिए) करती है, और कक्षा में विभिन्न अन्य तरीके इसे कहते हैं। हालाँकि, एक इकाई परीक्षण में, आप बाहरी डेटा स्रोत पर निर्भर नहीं होना चाहते हैं - इसलिए आप गतिशील रूप से get_data
स्टब के साथ विधि को प्रतिस्थापित करते हैं जो कुछ निश्चित डेटा लौटाता है।
क्योंकि पायथन कक्षाएं उत्परिवर्तनीय हैं, और विधियां केवल कक्षा की विशेषता हैं, आप इसे जितना चाहें उतना कर सकते हैं - और, वास्तव में, आप एक मॉड्यूल में कक्षाओं और कार्यों को बिल्कुल उसी तरह से बदल सकते हैं।
लेकिन, एक टिप्पणीकार ने कहा, जब बंदर पकड़ने पर सावधानी बरतें:
अगर आपके टेस्ट लॉजिक के अलावा कुछ और भी कॉल get_data
करता है, तो यह आपके बन्दर-पैच वाले रिप्लेसमेंट को ऑरिजिनल की बजाय बुलाएगा - जो अच्छा या बुरा हो सकता है। बस खबरदार।
यदि कुछ चर या विशेषता मौजूद है, जो get_data
उस समय तक आपके द्वारा प्रतिस्थापित किए जाने वाले फ़ंक्शन को भी इंगित करता है, तो यह उपनाम अपना अर्थ नहीं बदलेगा और मूल को इंगित करता रहेगा get_data
। (क्यों? पायथन सिर्फ get_data
आपकी कक्षा में नाम को किसी अन्य फ़ंक्शन ऑब्जेक्ट के लिए पुन: डिज़ाइन करता है; अन्य नाम बाइंडिंग सभी से प्रभावित नहीं होते हैं।)
get_data
, तो आप नाम get_data
को मॉक फ़ंक्शन के लिए रिबंड करते हैं । यदि कार्यक्रम में कहीं और कोई दूसरा नाम फ़ंक्शन-फ़ंक्शन-पूर्व-ज्ञात-जैसे से बंधा हुआ है get_data
, तो उस अन्य नाम के लिए कुछ भी नहीं बदलेगा।
मंकीपॉच पायथन कोड का एक टुकड़ा है जो रनटाइम पर (आमतौर पर स्टार्टअप में) अन्य कोड को बढ़ाता या संशोधित करता है।
एक साधारण उदाहरण इस तरह दिखता है:
from SomeOtherProduct.SomeModule import SomeClass
def speak(self):
return "ook ook eee eee eee!"
SomeClass.speak = speak
स्रोत: Zope विकी पर MonkeyPatch पेज।
एक बंदर पैच क्या है?
सीधे शब्दों में कहें, बंदर पैचिंग एक मॉड्यूल या वर्ग में परिवर्तन कर रहा है जबकि कार्यक्रम चल रहा है।
पंडों के दस्तावेज में बंदर-पेटिंग का एक उदाहरण है:
import pandas as pd
def just_foo_cols(self):
"""Get a list of column names containing the string 'foo'
"""
return [x for x in self.columns if 'foo' in x]
pd.DataFrame.just_foo_cols = just_foo_cols # monkey-patch the DataFrame class
df = pd.DataFrame([list(range(4))], columns=["A","foo","foozball","bar"])
df.just_foo_cols()
del pd.DataFrame.just_foo_cols # you can also remove the new method
इसे तोड़ने के लिए, पहले हम अपने मॉड्यूल को आयात करते हैं:
import pandas as pd
अगला हम एक विधि परिभाषा बनाते हैं, जो किसी भी वर्ग परिभाषाओं के दायरे से बाहर और बाहर मौजूद है (क्योंकि एक फ़ंक्शन और एक अनबाउंड विधि के बीच अंतर काफी अर्थहीन है, पायथन 3 अनबाउंड विधि से दूर हो जाता है):
def just_foo_cols(self):
"""Get a list of column names containing the string 'foo'
"""
return [x for x in self.columns if 'foo' in x]
आगे हम बस उस विधि को उस वर्ग से जोड़ते हैं जिसे हम उस पर प्रयोग करना चाहते हैं:
pd.DataFrame.just_foo_cols = just_foo_cols # monkey-patch the DataFrame class
और फिर हम कक्षा के एक उदाहरण पर विधि का उपयोग कर सकते हैं, और जब हम कर सकते हैं तब विधि को हटा दें:
df = pd.DataFrame([list(range(4))], columns=["A","foo","foozball","bar"])
df.just_foo_cols()
del pd.DataFrame.just_foo_cols # you can also remove the new method
यदि आप नाम-मैनलिंग (डबल-अंडरस्कोर के साथ प्रीफ़िक्सिंग विशेषताओं का उपयोग कर रहे हैं, जो नाम को बदल देता है, और जो मैं अनुशंसा नहीं करता है) यदि आप ऐसा करते हैं तो आपको मैन्युअल रूप से नाम-मैन्गल करना होगा। चूंकि मैं नाम-निर्माण की सिफारिश नहीं करता, इसलिए मैं इसे यहां प्रदर्शित नहीं करूंगा।
हम इस ज्ञान का उपयोग कैसे कर सकते हैं, उदाहरण के लिए, परीक्षण में?
मान लें कि हमें किसी डेटा पुनर्प्राप्ति कॉल को एक बाहरी डेटा स्रोत में अनुकरण करने की आवश्यकता है, जिसके परिणामस्वरूप त्रुटि होती है, क्योंकि हम ऐसे मामले में सही व्यवहार सुनिश्चित करना चाहते हैं। हम इस व्यवहार को सुनिश्चित करने के लिए डेटा संरचना को बंद कर सकते हैं। (इसलिए डैनियल रोज़मैन द्वारा सुझाए गए एक समान विधि नाम का उपयोग करके :)
import datasource
def get_data(self):
'''monkey patch datasource.Structure with this to simulate error'''
raise datasource.DataRetrievalError
datasource.Structure.get_data = get_data
और जब हम व्यवहार के लिए इसका परीक्षण करते हैं, जो इस पद्धति पर निर्भर करता है कि त्रुटि कैसे हुई, यदि इसे सही ढंग से लागू किया जाता है, तो हम उस व्यवहार को परीक्षा परिणामों में प्राप्त करेंगे।
बस ऊपर Structure
करने से प्रक्रिया के जीवन के लिए वस्तु बदल जाएगी , इसलिए आप ऐसा करने से बचने के लिए अपने unittests में setups और taddowns का उपयोग करना चाहते हैं:
def setUp(self):
# retain a pointer to the actual real method:
self.real_get_data = datasource.Structure.get_data
# monkey patch it:
datasource.Structure.get_data = get_data
def tearDown(self):
# give the real method back to the Structure object:
datasource.Structure.get_data = self.real_get_data
(जबकि इसके बाद के संस्करण ठीक है, यह शायद एक बेहतर विचार हो उपयोग करने के लिए होगा mock
कोड पैच करने के लिए पुस्तकालय। mock
के patch
डेकोरेटर कम त्रुटि ऊपर कर से होने का खतरा है, जो कोड के अधिक लाइनों और इस प्रकार अधिक त्रुटियों को पेश करने के अवसर की आवश्यकता होगी होगा । मुझे अभी तक इस कोड की समीक्षा करनी है mock
लेकिन मुझे लगता है कि यह इसी तरह से बंदर-पैचिंग का उपयोग करता है।)
विकिपीडिया के अनुसार :
पायथन में, बन्दर पैच शब्द केवल रनटाइम पर एक वर्ग या मॉड्यूल के गतिशील संशोधनों को संदर्भित करता है, मौजूदा थर्ड-पार्टी कोड को बग या सुविधा के लिए वर्कअराउंड के रूप में पैच करने के इरादे से प्रेरित होता है जो आपकी इच्छा के अनुसार कार्य नहीं करता है।
पहला: मंकी पैचिंग एक दुष्ट हैक (मेरी राय में) है।
यह अक्सर कस्टम कार्यान्वयन के साथ मॉड्यूल या वर्ग स्तर पर एक विधि को बदलने के लिए उपयोग किया जाता है।
जब आप मूल कोड को प्रतिस्थापित नहीं कर सकते, तो सबसे आम usecase एक बग या मॉड्यूल या वर्ग में बग के लिए समाधान जोड़ रहा है। इस मामले में आप "गलत" कोड को अपने स्वयं के मॉड्यूल / पैकेज के अंदर कार्यान्वयन के साथ बंदर पैचिंग के माध्यम से बदलते हैं।
बंदर पैचिंग केवल गतिशील भाषाओं में की जा सकती है, जिनमें से अजगर एक अच्छा उदाहरण है। ऑब्जेक्ट डेफिनिशन को अपडेट करने के बजाय रनटाइम पर एक विधि बदलना एक उदाहरण है, इसी तरह, रनटाइम पर विशेषताओं (चाहे तरीके या चर) को जोड़कर बंदर पैचिंग को माना जाता है। ये अक्सर तब किए जाते हैं जब मॉड्यूल के साथ काम करने के लिए आपके पास स्रोत नहीं होता है, जैसे कि ऑब्जेक्ट परिभाषाओं को आसानी से नहीं बदला जा सकता है।
इसे बुरा माना जाता है क्योंकि इसका मतलब है कि किसी वस्तु की परिभाषा पूरी तरह से या सटीक वर्णन नहीं करती है कि यह वास्तव में कैसे व्यवहार करती है।
मंकी पैचिंग रनटाइम के दौरान क्लास में मौजूदा क्लासेस या तरीकों को फिर से खोल रही है और व्यवहार को बदल रही है, जिसे सावधानी से इस्तेमाल किया जाना चाहिए, या आपको इसका उपयोग केवल तब करना चाहिए जब आपको वास्तव में ज़रूरत हो।
जैसा कि पायथन एक गतिशील प्रोग्रामिंग भाषा है, कक्षाएं परस्पर भिन्न होती हैं ताकि आप उन्हें फिर से खोल सकें और संशोधित कर सकें या उन्हें बदल भी सकें।
बंदर का पेटिंग क्या है?मंकी पैचिंग एक ऐसी तकनीक है जिसका इस्तेमाल रन-टाइम में कोड के एक टुकड़े के व्यवहार को गतिशील रूप से अपडेट करने के लिए किया जाता है।
बन्दर पैचिंग का उपयोग क्यों करें?यह हमें स्रोत कोड को संशोधित किए बिना रनटाइम पर पुस्तकालयों, मॉड्यूल, वर्गों या विधियों के व्यवहार को संशोधित करने या विस्तारित करने की अनुमति देता है
निष्कर्ष बंदर पैचिंग एक शांत तकनीक है और अब हमने सीखा है कि पायथन में ऐसा कैसे किया जाए। हालांकि, जैसा कि हमने चर्चा की, इसकी अपनी कमियां हैं और इसका सावधानी से उपयोग किया जाना चाहिए।
अधिक जानकारी के लिए कृपया देखें [1]: https://medium.com/@nagillavenkatesh1234/monkey-patching-in-python-explained-with-examples-25eed0aea505
pointing to the original get_data function
? क्या आपका मतलब है जब आप एक चर के अंदर एक फ़ंक्शन को स्टोर करते हैं यदि कोई व्यक्ति उस फ़ंक्शन को बदलता है जो चर पुराने को इंगित करता रहेगा?