2009-04-04 17 views
14

रूबी के बारे में मैंने कई चर्चाओं में सुना है जिसमें लोगों ने भाषा के बारे में अपना आरक्षण व्यक्त किया है, बंदर पैचिंग का मुद्दा उनकी प्राथमिक चिंताओं में से एक के रूप में आता है।यदि रूबी और पायथन दोनों में बंदर पैचिंग की अनुमति है, तो रूबी में यह और अधिक विवादास्पद क्यों है?

हालांकि, मैं शायद ही कभी पाइथन के संदर्भ में किए गए समान तर्क सुनता हूं हालांकि इसे पायथन भाषा में भी अनुमति है।

यह भेद क्यों?

क्या पाइथन में इस सुविधा के जोखिम को कम करने के लिए विभिन्न प्रकार के सुरक्षा उपाय शामिल हैं?

+1

पाइथन की तुलना में जावास्क्रिप्ट में यह अधिक आम है, संभवतः रूबी में जितना आम है, अगर –

उत्तर

16

एक अजगर प्रोग्रामर जो रूबी का स्वाद था (और यह पसंद करती है) गया है, मुझे लगता है कि पाइथन लोकप्रिय होने लगने के लिए कुछ हद तक एक विडंबनात्मक समानांतर है।

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

// Java 
Person p = new Person(); 
# Python 
p = Person() 

हम कुछ और गतिशील सुविधाओं जावा के बाद के संस्करणों में दिखाई देते हैं को देखने के लिए शुरू कर दिया। Autoboxing और -unboxing प्राइमेटिव से निपटने के लिए इसे कम परेशानी बनाते हैं, और जेनेरिक हमें एक बार कोड करने और इसे कई प्रकारों पर लागू करने की अनुमति देते हैं।

यह कुछ मनोरंजन के साथ था कि मैंने रूबी - बंदर पैचिंग की प्रमुख लचीली विशेषताओं में से एक देखा, जिसे पाइथन भीड़ द्वारा खतरनाक माना जाता है। इस वर्ष छात्रों को रूबी को पढ़ाना शुरू करने के बाद, मुझे लगता है कि मौजूदा वर्ग के कार्यान्वयन को ठीक करने में सक्षम होने के नाते, यहां तक ​​कि सिस्टम का हिस्सा भी बहुत शक्तिशाली है।

निश्चित रूप से, आप बुरी तरह खराब हो सकते हैं और आपका प्रोग्राम क्रैश हो सकता है। मैं भी आसानी से सी में segfault कर सकते हैं। और जावा ऐप फ्लेमिंग मौत मर सकता है।

सच्चाई यह है कि मैं गतिशील और मेटा प्रोग्रामिंग में अगले चरण के रूप में बंदर पैचिंग देखता हूं। मजेदार, चूंकि यह स्मॉलटॉक के आसपास रहा है।

+3

मैंने "बतख-पंचिंग" शब्द को उसी नस में इस्तेमाल किया है जैसे "बंदर-पैचिंग "। यह "बतख टाइपिंग" पर एक नाटक है (यदि यह एक बतख की तरह quacks, तो यह एक बतख भी हो सकता है, भले ही यह एक पूर्णांक है)। यदि यह एक बतख की तरह रैक नहीं करता है, तो आप इसे तब तक पंच करते हैं जब तक यह करता है (नई विधियां, आदि जोड़ें)। –

15

भाषाएं इसे अनुमति दे सकती हैं, लेकिन न तो समुदाय इस अभ्यास को स्वीकार करता है। बंदरपैचिंग को किसी भी भाषा में नहीं माना जाता है, लेकिन आप इसके बारे में रूबी में अधिक बार सुनते हैं क्योंकि खुले वर्ग के रूप में इसका उपयोग कक्षा को बंदरगाह के लिए बहुत आसान बनाता है और इसके कारण it's more acceptable in the Ruby community, but still frowned upon। बंदरगाह बस पाइथन में प्रचलित या आसान नहीं है, यही कारण है कि आप उस समुदाय में इसके खिलाफ एक ही तर्क नहीं सुनेंगे। पाइथन ऐसा कुछ नहीं करता है जो रूबी अभ्यास को रोकने के लिए नहीं करता है।

class MyClass 
    def foo 
    puts "foo" 
    end 
end 
class MyClass 
    def bar 
    puts "bar" 
    end 
end 

आप एक वर्ग है कि दो तरीकों, foo और bar होता है, पायथन में दे देंगे इस जबकि:

कारण आप रूबी में सुना है/इसके बारे में पढ़ा अधिक बार है कि रूबी इस में है :

class MyClass: 
    def foo(self): 
     print "foo" 
class MyClass: 
    def bar(self): 
     print "bar" 

आप एक वर्ग है कि केवल मीटर शामिल हैं के साथ छोड़ देंगे § bar, एक कक्षा के पुनर्वितरण के रूप में पिछली परिभाषा पूरी तरह से। अजगर में monkeypatch करने के लिए, आप वास्तव में यह लिखने के लिए है:

class MyClass: 
    def foo(self): 
     print "foo" 
def bar(self): 
    print "bar" 
MyClass.bar = bar 

जो रूबी संस्करण की तुलना में कठिन है। वह अकेले रूबी कोड को पायथन कोड की तुलना में बंदरगाह के लिए बहुत आसान बनाता है।

+0

अधिक नहीं है तो आपका पायथन उदाहरण वैध भी है। दूसरी परिभाषा सिर्फ एक नया MyClass-class बनाता है और पिछले एक को विस्तारित नहीं करता है (मुझे लगता है कि रूबी क्या करता है)। –

+0

आपको एक नोट जोड़ना चाहिए कि यह तकनीकी रूप से मान्य है – hasen

+0

क्या आप कुछ संदर्भ प्रदान कर सकते हैं जो रुबी "समुदाय" को अभ्यास को न मानने से दिखाता है? ActiveSupport :: CoreExtensions के बारे में क्या? –

13

"क्या पाइथन में इस सुविधा के जोखिम को कम करने के लिए विभिन्न प्रकार के सुरक्षा उपाय शामिल हैं?"

हां। समुदाय इसे करने से इंकार कर देता है। सुरक्षा पूरी तरह से सामाजिक है।

21

यह एक तकनीक है जो पाइथन में कम अभ्यास करती है, क्योंकि कुछ हिस्सों में पाइथन (सी में लागू किए गए) वास्तव में संशोधित नहीं हैं। दूसरी तरफ रूबी में, जिस तरह से इसे आंतरिक रूप से लागू किया गया है (बेहतर नहीं, बिल्कुल अलग) क्योंकि कुछ भी गतिशील रूप से संशोधित किया जा सकता है।

दार्शनिक रूप से, यह कुछ ऐसा है जो पाइथन समुदाय के भीतर फंस जाता है, जो रूबी दुनिया में काफी कम है। मुझे नहीं पता कि आप क्यों दावा करते हैं कि यह अधिक विवादास्पद है (क्या आप एक आधिकारिक संदर्भ से लिंक कर सकते हैं?) - मेरा अनुभव यह रहा है कि बंदर-पैचिंग एक स्वीकार्य तकनीक है यदि उपयोगकर्ता को संभावित परिणामों के बारे में पता होना चाहिए।

+0

मैं रूबी समुदाय के बारे में बात नहीं कर सकता हूं इसलिए मैं आपका शब्द ले जाऊंगा कि बंदरगाहिंग वहां स्वीकार की जाती है, लेकिन यदि आप पाइथन डेवलपर्स से भरे कमरे में जाते हैं और उनसे पूछें कि वे रूबी के बारे में क्या सोचते हैं, तो आप की तुलना में अधिक संभावना है शब्द "बंदर पैचिंग" नहीं सुनना, और सकारात्मक प्रकाश में नहीं। –

+0

हां, लेकिन 'पायथन प्रोग्रामर के बीच विवादास्पद' रूब प्रोग्रामर के बीच 'controverial' से अलग है। हालांकि पाइथन में बंदर-पैचिंग करना संभव है (और कभी-कभी उपयोगी लेकिन खतरनाक के रूप में पहचाना जाता है), रूबी की कई भाषा विशेषताएं हैं जो सक्रिय रूप से इसे प्रोत्साहित करती हैं। –

+0

(argh, जो कि 'रूबी प्रोग्रामर' के बीच 'विवादास्पद' होना चाहिए, बेशक ...) –

3

असल में पायथन में बुनियादी प्रकारों को संशोधित करना थोड़ा कठिन है।

उदाहरण के लिए कल्पना करें कि आप पूर्णांक को फिर से परिभाषित करते हैं।

रूबी:

class Fixnum 
    def *(n) 
     5 
    end 
end 

अब 2 * 2 पैदावार 5.

पायथन:

>>> class int(int): 
    def __mul__(self, x): 
     return 5 


>>> 2*2 
4 
>>> int(2)*int(2) 
5 
+0

वह रूबी उदाहरण जो आपको लगता है वह नहीं करता है। इससे ऐसा होगा ताकि आप Integer.times {| पांच | "संख्या # {पांच + 1}"} से कम है और यह 6 * 2 * वापस आ जाएगी, हालांकि, अभी भी 4 होगी। आप कक्षा फिक्सम चाहते हैं; डीफ़ * (एन); 5; समाप्त; समाप्त । – Chuck

+0

@Chuck: धन्यवाद, मुझे वास्तव में रूबी (अभी तक) के साथ बहुत अधिक अनुभव नहीं मिला है, मैं एक पाइथन लड़का हूं ;-) – vartec

3

अजगर में, किसी भी शाब्दिक ("", {}, 1.0, आदि) मानक वर्ग का एक उदाहरण बनाता है, भले ही आप इसे monkeypatch करने की कोशिश की और अपने नाम स्थान में इसी वर्ग नए सिरे से परिभाषित।

यह सिर्फ काम नहीं करेगा आप कैसे इरादा:

class str(): 
    # define your custom string type 
    ... 

a = "foo"  # still a real Python string 
a = str("foo") # only this uses your custom class 
+0

रूबी एक ही तरीके से काम करता है, इसलिए *** *** *** एक अंतर नहीं है। अगर मैं स्ट्रिंग। नया (* तर्क, और ब्लॉक) def; सरणी।नया; एंडी 'रूबी में, फिर भी' स्ट्रिंग.न्यू ("foo") 'में परिणाम' [] ', '" foo "' अभी भी '' foo '' में परिणाम हैं। –

+0

रूबी के इस बिट पर विचार करें: –

2

मुझे लगता है कि बंदर पैचिंग केवल पिछले समाधान के रूप में इस्तेमाल किया जाना चाहिए।

आम तौर पर पायथन प्रोग्रामर जानते हैं कि कक्षा या विधि कैसे व्यवहार करती है। वे जानते हैं कि कक्षा xxx एक निश्चित तरीके से चीजें कर रहा है।

जब आप बंदर वर्ग या विधि को पैच करते हैं, तो आप इसका व्यवहार बदल रहे हैं। इस वर्ग का उपयोग करने वाले अन्य पायथन प्रोग्रामर आश्चर्यचकित हो सकते हैं यदि वह वर्ग अलग-अलग व्यवहार कर रहा है।

चीजों को करने का सामान्य तरीका subclassing है। इस तरह, अन्य प्रोग्रामर जानते हैं कि वे एक अलग वस्तु का उपयोग कर रहे हैं। यदि वे चुनते हैं तो वे मूल वर्ग या उप-वर्ग का उपयोग कर सकते हैं।

+0

यदि कोई स्क्रिप्ट का उपयोग करके कोई अन्य पायथन प्रोग्रामर नहीं हैं तो क्या होगा? या लिपि छोटी है? 50 + केएलओसी परियोजना से निपटने के दौरान हम जो 'खतरनाक' तर्क सुनते हैं, वे बहुत मान्य हैं। छोटी लिपियों के लिए, हालांकि, पैसा पैच करने में सक्षम नहीं होने का मतलब एक स्क्रिप्ट के लिए बॉयलरप्लेट की सैकड़ों लाइनों का मतलब हो सकता है जो अन्यथा कुछ पंक्तियों तक लंबा होगा। मुझे छोटी लिपियों के लिए 'मैला पायथन' पसंद आएगा (जहां कोई सक्षम प्रोग्रामर कुछ मिनटों में पूरी चीज को पढ़ और याद कर सकता है)। अधिकांश सॉफ्टवेयर इंजीनियरिंग विषयों बड़ी परियोजनाओं के लिए हैं। –

1

यदि आप पाइथन में कुछ बंदर पैचिंग करना चाहते हैं, तो यह अपेक्षाकृत आसान है, जब तक कि आप अंतर्निर्मित प्रकार (int, float, str) को संशोधित नहीं कर रहे हैं।

class SomeClass: 
    def foo(self): 
     print "foo" 

def tempfunc(self): 
    print "bar" 
SomeClass.bar = tempfunc 
del tempfunc 

यह SomeClass बार विधि जोड़ देगा और उस वर्ग के भी मौजूदा उदाहरणों कि इंजेक्शन विधि का उपयोग कर सकते हैं।

+0

इसके अलावा-बंदर-पैच करने योग्य नहीं: datetime.datetime, datetime.timedelta, और कई, कई और। शर्म की बात है, क्योंकि ऐसे तरीके हैं जिन्हें मैं अक्सर इन वर्गों का विस्तार करना चाहता हूं। –

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