2012-12-26 6 views
7

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

>>> def makeAdder(y): 
... def myAdder(x): 
... return x + y 
... return myAdder 
... 
>>> f = makeAdder(10) 
>>> f(5) 
15 

मैं समझता हूं कि यह कुछ अर्थों में उपयोगी हो सकता है। हालांकि, वास्तविक, इस तरह की स्थितियों में व्यवहार (स्थितियों 'केवल पढ़ने के लिए' क्योंकि यह थे) आसानी से एक वस्तु (एक functor) ने अपनाया जा सकता है:

>>> class MyAdder(object): 
... def __init__(self,y): 
... self.y = y 
... def __call__(self,x): 
... return self.y + x 
... 
>>> f = MyAdder(5) 
>>> f(10) 
15 

वस्तु नहीं ऊपर काफी अधिक स्थान के लिए ले करता कोड, और यह कहीं अधिक बहुमुखी है। बाद के कोड को ट्रैक और डीबग करना भी बहुत आसान है।

इस मामले में, हम केवल nonlocal चर से पढ़ते हैं। लेकिन हम इसे भी लिख सकते हैं: स्वाभाविक रूप से, पाइथन में nonlocal कीवर्ड का उपयोग करके। ऑब्जेक्ट भी निश्चित रूप से समर्थन करता है। लेकिन ऑब्जेक्ट के साथ, आपके पास डेटा एक साथ बंडल किया गया है ताकि आप जान सकें कि वास्तव में क्या हो रहा है। बंद हो सकता है संभावित रूप से पूरी तरह से गैर-पारदर्शी तरीके से चर के चारों ओर ले जाया जा सकता है और यह कोड को जन्म दे सकता है जो डीबग करने के लिए आश्चर्यजनक रूप से कठिन है।

irb(main):001:0> def new_counter 
irb(main):002:1> x = 0 
irb(main):003:1> lambda { x +=1 } 
irb(main):004:1> end 
=> nil 
irb(main):005:0> counter_a = new_counter 
=> #<Proc:[email protected](irb):3> 
irb(main):006:0> counter_a.call 
=> 1 
irb(main):007:0> counter_a.call 
=> 2 

कम से कम मेरे लिए, इस व्यवहार unintuitive है: यहाँ एक बहुत विचित्र उदाहरण है। इसमें मेमोरी लीक का कारण बनने की क्षमता भी है। यह आपको अपने आप को लटका देने के लिए रस्सी की एक बड़ी राशि देता है। दोबारा, यह रूबी में विशेष रूप से सच है जहां आपको इसे स्पष्ट रूप से सक्षम करने की आवश्यकता नहीं है (पायथन के विपरीत), और क्योंकि रूबी में अपने सभी मुख्य कोड को अवरुद्ध कर दिया गया है, जिनके पास सबकुछ तक पहुंच है। यदि बंद होने के परिणामस्वरूप बाहरी चर बदल जाता है, तो यदि आप अपने आस-पास के पास को पास करते हैं तो आपके पास एक स्थान बदल सकता है जहां से यह रहता है, उस स्थान से अनिश्चित काल तक और दायरे से बाहर हो सकता है। किसी ऑब्जेक्ट की तुलना करें जो हमेशा इसके साथ अपने डेटा को सुरक्षित रखती है।

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

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

संपादित 2: मैंने तीसरे उपयोग के बंद होने से विचित्र व्यवहार का एक उदाहरण दिया, गैर स्थानीय चरों को लिखना।यहाँ विचित्र (बुरा के रूप में नहीं) दूसरे के उपयोग से व्यवहार का एक उदाहरण है (स्कोप में बंद को परिभाषित जहां उनके बंद से अधिक चर संशोधित किया जा सकता):

>>> fs = [(lambda n: i + n) for i in range(10)] 
>>> fs[4](5) 
14 
+0

मैं रूबी पता नहीं है, इसलिए मैं नहीं जानता कि यदि स्मृति के अपने दावे लीक यथार्थवादी है। यह पायथन में कोई मुद्दा नहीं है, शायद आप उस बिंदु को स्पष्ट कर सकते हैं? –

+0

सहमत हैं, विशेष रूप से मुझे नहीं पता कि * अविश्वसनीय रूप से खतरनाक * कहां से आता है। –

+1

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

उत्तर

10

पठनीयता। आपका पायथन उदाहरण दिखाता है कि बंद संस्करण को पढ़ने के लिए कितना अधिक स्पष्ट और आसान है, इसकी तुलना मज़ेदार से की जाती है।

हम अच्छी तरह से एक कक्षा बनाने से बचते हैं जो कुछ भी नहीं करता बल्कि कार्य की तरह कार्य करता है - यह अनावश्यकता की गंध करता है।

यदि कुछ और नहीं है, तो हम कुछ कर रहे हैं, it makes sense to describe it as an action, not an object

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

संपादित करें: राज्य पर एक नोट के रूप में, याद रखें कि कार्यों अजगर में विशेष नहीं हैं, वे कर रहे हैं अभी भी वस्तुओं:

>>> def makeAdder(y): 
...  def myAdder(x): 
...   return x + myAdder.y 
...  myAdder.y = y 
...  return myAdder 
... 
>>> f = makeAdder(10) 
>>> f(5) 
15 
>>> f.y 
10 
+1

मुझे लगता है कि यह स्वाद का विषय है।मैं व्यक्तिगत रूप से सहमत हूं, लेकिन मुझे बहुत से लोगों का सामना करना पड़ा है जो कार्यों को वापस लाने में मुश्किल लगने के विचारों को समझते हैं, क्योंकि बाहरी बनाम आंतरिक कार्यों को बुलाए जाने पर उन्हें अपने सिर को पाने में परेशानी होती है। – BrenBarn

+3

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

+1

मुझे लगता है कि कोई पूछ सकता है कि यह वास्तव में वास्तव में अधिक पठनीय है या नहीं। आखिरकार: यह सिर्फ एक समारोह नहीं है, इसमें राज्य भी है। इसके अतिरिक्त, अगर आपको बाद में राज्य के बारे में कुछ भी जांचने की ज़रूरत है, तो यह किसी ऑब्जेक्ट के साथ बहुत आसान है। –

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