2010-04-16 10 views
6

मैं से WikiVS से कुछ पृष्ठों से अधिक जा रहा था, कि मैं बोली:Restrictons: लैम्ब्डा के

क्योंकि पायथन में lambdas भाव तक ही सीमित हैं और नहीं बयानों को शामिल कर सकते

मैं जानना चाहता हूं कि एक अच्छा उदाहरण क्या होगा (या अधिक) जहां यह प्रतिबंध होगा, अधिमानतः रूबी भाषा की तुलना में।

आपके उत्तरों, टिप्पणियों और प्रतिक्रिया के लिए धन्यवाद!

+2

लैम्बडास अभिव्यक्ति * द्वारा अभिव्यक्ति * हैं। –

उत्तर

12

मुझे नहीं लगता कि आप वास्तव में लैम्बडास के बारे में पूछ रहे हैं, लेकिन इनलाइन फ़ंक्शन

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

जावास्क्रिप्ट:

responses = { 
     "resp1": { 
       "start": function() { ... }, 
       "stop": function() { ... }, 
     }, 
     "resp2": { 
       "start": function() { ... }, 
       "stop": function() { ... }, 
     }, 
     ... 
} 
responses["resp1"]["start"](); 

लुआ:

responses = { 
     resp1 = { 
       start = function() ... end; 
       end = function() ... end; 
     }; 
     ... 
} 
responses.resp1.start(); 

रूबी:

responses = { 
    "resp1" => { 
     "start" => lambda { }, 
     "stop" => lambda { }, 
    }, 
} 
responses["resp1"]["start"].call 

पायथन:

def resp1_start(): 
    pass 
def resp1_stop(): 
    pass 
responses = { 
    "resp1": { 
     "start": resp1_start, 
     "stop": resp1_stop, 
    }, 
} 
responses["resp1"]["start"]() 

ध्यान दें कि जावास्क्रिप्ट और लुआ में लैम्बडा नहीं हैं: उनके पास मौजूद होने का कोई कारण नहीं है, क्योंकि इनलाइन फ़ंक्शंस उन्हें अधिक प्राकृतिक और सामान्य तरीके से कवर करते हैं।

मैं शायद इसे सबसे ज्यादा परेशान दिन-दर-दिन पायथन सीमा के रूप में रेट करूंगा।

+1

.. यह एक बदसूरत हैक है .. << क्या आपके पास लिंक हैं जो इसे इंगित करते हैं? – Shyam

+2

मैंने रूबी के दूसरे श्रेणी के "इनलाइन फ़ंक्शन" तंत्र का एक उदाहरण दिया। –

+6

@Glenn, रूबी के पास बिल्कुल काम नहीं है, इसमें केवल विधियां हैं। रुबी के अज्ञात फ़ंक्शन (लैम्ब्डा फ़ंक्शन) वास्तव में फ़ैक्टर हैं। और उनके बारे में बदसूरत या हैक जैसी कुछ भी नहीं है। यह केवल संदेश-पास ओओ का एक परिणाम है। स्कैला वही काम करता है, तो स्मॉलटाक करता है। – horseyguy

9

विवरणों के बारे में सबसे आम स्थिति शायद पाइथन 2.X का print कथन है।

उदाहरण के लिए,

say_hi = lambda name: "Hello " + name 

काम करता है के रूप में उम्मीद।

लेकिन इस संकलन नहीं होगा:

:

क्योंकि
say_hi = lambda name: print "Hello " + name 

print पायथन में एक उचित समारोह 2.

>>> say_hi = lambda name: "Hello " + name 
>>> say_hi("Mark") 
'Hello Mark' 
>>> 
>>> say_hi = lambda name: print "Hello " + name 
SyntaxError: invalid syntax 

print अलावा बयान के बाकी in the Python documentation online पाया जा सकता है नहीं है

simple_stmt ::= expression_stmt 
       | assert_stmt 
       | assignment_stmt 
       | augmented_assignment_stmt 
       | pass_stmt 
       | del_stmt 
       | print_stmt 
       | return_stmt 
       | yield_stmt 
       | raise_stmt 
       | break_stmt 
       | continue_stmt 
       | import_stmt 
       | global_stmt 
       | exec_stmt 

आप आरईपीएल में इन में से बाकी की कोशिश कर सकते हैं यदि आप उन्हें असफल देखना चाहते हैं:

>> assert(True) 
>>> assert_lambda = lambda: assert(True) 
SyntaxError: invalid syntax 
>>> pass 
>>> pass_lambda = lambda: pass 
SyntaxError: invalid syntax 

मुझे यकीन है कि क्या समानताएं वहाँ पायथन के lambda प्रतिबंध और रूबी के proc या lambda के बीच हैं नहीं कर रहा हूँ। रूबी में, सबकुछ एक संदेश है, इसलिए आपके पास कीवर्ड नहीं हैं (ठीक है, आपके पास कीवर्ड हैं, लेकिन आपके पास ऐसे कीवर्ड नहीं हैं जो पाइथन के print जैसे फ़ंक्शंस दिखाई देते हैं)। मेरे सिर के ऊपर से, कोई आसानी से गलत रूबी संरचना नहीं है जो proc में विफल हो जाएगी।

+1

इसे लिखने के लिए आपके समय के लिए धन्यवाद! – Shyam

4

एक उदाहरण है कि गया है कभी कभी मेरे साथ ऊपर आ कुछ इस तरह है:

def convert(value): 
    n = expensive_op(value) 
    return (n, n + 1) 

new_list = map(convert, old_list) 

हालांकि यह छोटी और पर्याप्त मीठा होता है, तो आप इसे एक लैम्ब्डा को expensive_op() दो बार चलाने के लिए बिना परिवर्तित नहीं कर सकते हैं (जो जैसा कि नाम से पता चलता है, आप नहीं करना चाहते हैं), यानी आप

new_list = map(lambda v: (expensive_op(v), expensive_op(v) + 1), old_list) 

है क्योंकि काम (n = ...) ने एक बयान है होगा।

+0

'new_list = map (lambda v: tuple (x.next() + y x के लिए x, y ज़िप में (* (itertools.tee ([महंगा_ओपी (v)]), (0, 1))), पुरानी_सूची) 'ऐसा नहीं है कि आप कभी भी ऐसा कुछ भी लिखेंगे, निश्चित रूप से ... –

+0

@Ignacio: ठीक है, मैं * जवाब के लिए ऐसा विकल्प जोड़ने के बारे में सोच रहा था। लेकिन इसके बारे में सोचने के बारे में सोच भी ;-) – balpha

+0

'new_list = [(आर, आर + 1) आर में (old_op (v) old_list में v के लिए)] '- यह एक बार चलाया जाता है और आंतरिक अभिव्यक्ति आलसी है, इसलिए यह मूल्यांकन करता है और आवश्यकतानुसार एक ट्यूपल बनाता है - केवल बाहरी सूची वास्तव में बनाई जाती है। – viraptor

1

lambda एक सरल अभिव्यक्ति देता है जो एक समारोह को परिभाषित करने के लिए पाइथन में बस एक शॉर्टकट तरीका है। यह किसी भी सार्थक तरीके से प्रतिबंध नहीं है। यदि आपको एक से अधिक अभिव्यक्ति की आवश्यकता है तो बस एक फ़ंक्शन का उपयोग करें: कुछ भी नहीं आप एक लैम्ब्डा के साथ कर सकते हैं जिसे आप किसी फ़ंक्शन के साथ नहीं कर सकते हैं।

लैम्ब्डा के बजाए फ़ंक्शन का उपयोग करने का एकमात्र नुकसान यह है कि फ़ंक्शन को 1 या अधिक अलग लाइनों पर परिभाषित किया जाना चाहिए (इसलिए आप लैम्ब्डा की तुलना में कुछ इलाके खो सकते हैं), और आपको एक नाम का आविष्कार करना होगा फ़ंक्शन (लेकिन यदि आप एक के बारे में नहीं सोच सकते हैं तो f आम तौर पर काम करता है)।

अन्य सभी कारणों से लोगों को लगता है कि उन्हें लैम्ब्डा का उपयोग करना है (जैसे नेस्टेड चर का उपयोग करना या अलग-अलग डिफ़ॉल्ट तर्कों के साथ बहुत सारे लैम्ब्स उत्पन्न करना) एक समारोह के साथ ही काम करेगा।

नामित फ़ंक्शन का उपयोग करने का बड़ा लाभ यह है कि जब यह गलत हो जाता है तो आपको सार्थक स्टैक ट्रेस मिलता है। मैंने कल मुझे काट दिया था जब मुझे एक लैम्ब्डा से ढेर एक स्टैक ट्रेस मिला था और यह कोई संदर्भ नहीं था कि यह कौन सा लैम्ब्डा था।

+0

आपको कार्यों की तरह, लैम्बडास के लिए बैकट्रैस में संदर्भ प्राप्त करना चाहिए। –

+0

आप करते हैं, लेकिन इस मामले में स्टैक ट्रेस शिकायत कर रहा था कि यह लैम्ब्डा को नहीं उठा सकता है, इसलिए लैम्ब्डा वास्तव में कॉल स्टैक का हिस्सा नहीं था। यदि यह एक स्थानीय समारोह था तो कम से कम मेरा नाम होगा। यदि आपको कुछ कॉल करने का प्रयास करते समय गलत तर्क हैं तो आपको एक ही समस्या मिलती है: बैकट्रैक में TypeError उत्पन्न करने योग्य कॉल करने योग्य के लिए कोई संदर्भ शामिल नहीं है। – Duncan

2

f=lambda s:pass के बजाय आप f=lambda s:None कर सकते हैं।

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