लैम्ब्डा में असाइनमेंट के लिए पायथन वर्कअराउंड


34

यह पायथन में गोल्फ के लिए एक टिप्स सवाल है।

पायथन गोल्फिंग में, एक फंक्शन को लैम्बडा के रूप में परिभाषित करने के लिए प्रस्तुत किया जाना आम है। उदाहरण के लिए,

f=lambda x:0**x or x*f(x-1)

भाज्य की गणना करता हैx की ।

मेमने के प्रारूप के दो बड़े फायदे हैं :

  • की बॉयलरप्लेट f=lambda x:...या lambda x:...तुलना में कम है def f(x):...return...याx=input()...print...
  • थोड़ा बाइट ओवरहेड के साथ लूप करने के लिए एक पुनरावर्ती कॉल का उपयोग किया जा सकता है।

हालाँकि, लंबोदर को केवल एक ही अभिव्यक्ति की अनुमति देने का बड़ा दोष है, कोई बयान नहीं। विशेष रूप से, इसका मतलब कोई असाइनमेंट नहीं हैc=chr(x+65) । यह तब समस्याग्रस्त होता है जब किसी की लंबी अभिव्यक्ति होती है, जिसके मूल्य को दो बार (या अधिक) संदर्भित करने की आवश्यकता होती है।

E=enumerateफ़ंक्शन के बाहर या वैकल्पिक तर्क के रूप में असाइनमेंट संभव हैं, लेकिन केवल तभी जब वे फ़ंक्शन इनपुट पर निर्भर न हों। वैकल्पिक तर्क f=lambda n,k=min(n,0):...विफल हो जाते हैं क्योंकि इनपुट nको परिभाषित नहीं किया गया है जबkपरिभाषा के समय पर मूल्यांकन ।

इसका परिणाम यह होता है कि कभी-कभी आप लंबोदर में एक लंबी अभिव्यक्ति को दोहराते हैं क्योंकि विकल्प लंबा लम्बा होता है।

lambda s:s.strip()+s.strip()[::-1]
def f(s):t=s.strip();print t+t[::-1]

विराम बिंदु 11 वर्णों ( विवरणों ) के बारे में है, अतीत जिसे आप defया तो बदल देते हैं program। दोहराया अभिव्यक्ति के लिए लंबाई 5 के सामान्य ब्रेक-सम प्वाइंट तक इसकी तुलना करें:

range(a)+range(b)
r=range;r(a)+r(b)

print s[1:],s[1:]*2
r=s[1:];print r,r*2

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


इस सीमा के आसपास एक पायथन गोल्फर से पार पाने या काम करने के तरीके क्या हैं? जब वे लंबोदर में दो बार दोहराए गए एक लंबे अभिव्यक्ति को देखते हैं तो उनके पास क्या संभावित विचार होने चाहिए?

इस सुझाव के साथ मेरा लक्ष्य इस समस्या में गहरा गोता लगाना है और:

  • कैटलॉग और एक लैम्ब्डा के अंदर नकली असाइनमेंट में गोल्फिंग वर्कआर्स का विश्लेषण करें
  • बेहतर तरीकों के लिए नए लीड का अन्वेषण करें

प्रत्येक उत्तर को वर्कअराउंड या संभावित लीड की व्याख्या करनी चाहिए।


मुझे लगता है कि यह उन चीजों में से एक है जो पायथन में अच्छी तरह से नहीं किया जा सकता है। जावास्क्रिप्ट इस पर एक पैर है।
mbomb007

बस ओर्लप के जवाब के साथ, नेस्टेड लैम्ब्डा का उपयोग करने के लिए नील (हटाए गए) सुझाव जरूरी नहीं है कि आप उन मामलों में बचाव से ज्यादा लंबे समय तक रहें जहां आपको एक नेस्टेड लैम्ब्डा की आवश्यकता होती है। मुझे लगता है कि यह अधिक गहन विश्लेषण के योग्य है।
मार्टिन एंडर

2
उल्टे लोअरकेस स्ट्रिंग कॉन्सेप्टन के साथ दिए गए सटीक उदाहरण के लिए बस जा सकते हैं lambda s:(s+s[::-1]).lower()। बेशक यह वास्तविक प्रश्न का उत्तर नहीं देता है।
जोनाथन एलन

@JonathanAllan अच्छा बिंदु, ने इसे बदल दिया strip
xnor

जवाबों:


6

eval

यह अपने आप में महान नहीं है, लेकिन यदि आपका समाधान पहले से ही evalकिसी तरह या रूप में उपयोग करता है , तो आप आमतौर पर इस तकनीक का उपयोग कर सकते हैं।

eval("%f*%f+%f"%((5**.5,)*3))

वाह, यह स्मार्ट है! मुझे इस तरह का कोड क्यों नहीं दिखता?
z0rberg के

6
@ z0rberg की संभवतः इसलिए क्योंकि बुराई बुराई है।
हाइपरन्यूट्रिनो

मैं इस कोडवाद की सदस्यता नहीं लेता। #EvalLivesMatter ... लेकिन गंभीरता से, यह साधारण डीएल-इंजेक्शन से भी बदतर कैसे है?
z0rberg की

6

पायथन 3.8 में असाइनमेंट अभिव्यक्ति

पायथन 3.8 ( टीआईओ ) असाइनमेंट एक्सप्रेशन पेश करता है , जो :=अभिव्यक्ति के हिस्से के रूप में एक वैरिएबल इनलाइन असाइन करने के लिए उपयोग करते हैं।

>>> (n:=2, n+1)
(2, 3)

यह एक अंदर इस्तेमाल किया जा सकता है lambda , जहां असाइनमेंट की अनुमति नहीं है। की तुलना करें:

lambda s:(t:=s.strip())+t[::-1]
lambda s:s.strip()+s.strip()[::-1]
def f(s):t=s.strip();return t+t[::-1]

इस टिप को और देखें ।


2

भीतर का लंबोदर

ये आपको एक साथ कई चर को परिभाषित करने की अनुमति देते हैं।

lambda s:s.strip()+s.strip()[::-1]

बनाम

lambda s:(lambda t:t+t[::-1])(s.strip())

बहुत लंबा है, लेकिन यदि आपके पास कई चर, या चर हैं जो लंबे हैं, जिन्हें कई बार दोहराया जाता है:

lambda a,b,c:a.upper()*int(c)+b.lower()*int(c)+a.upper()[::-1]+b.lower()[::-1]+a.upper()*int(c)+a.lower()*int(c)

बनाम

lambda a,B,c:(lambda A,b,n:A*n+b*n+A[::-1]+b[::-1]+A*n+b*c)(a.upper(),B.lower(),int(c))

अक्षर गणना

आरंभिक: (lambda:)()(11 बाइट्स)
पहला चर: [space]a(2 बाइट्स)
बाद के चर: ,b,(3 बाइट्स)
उपयोग: a(1 बाइट्स )।

(lambda* a*_,b_:)(*<value a>*_,<value b>_)

(कोष्ठक पर भी बचत होती है)

तो, यह 3n + 10बाइट्स लेता है , जहांn चर की संख्या है। यह एक उच्च प्रारंभिक लागत है, लेकिन अंत में भुगतान कर सकते हैं। यह आंतरिक मूल्य भी देता है, इसलिए आप कई बार घोंसला बना सकते हैं (हालांकि यह जल्दी से इसके लायक नहीं होगा।)

यह वास्तव में केवल नेस्टेड सूची समझ में लंबी मध्यवर्ती गणनाओं के लिए उपयोगी है, एक के रूप में def f():a=...;b=...;return आमतौर पर कम होगा।

1 मान के लिए, यह बचाता है: uses * length - length - uses - 13तो केवल तभी उपयोगी है जब वह अभिव्यक्ति सकारात्मक हो। कुल मिला कर उपयोग किए गए विभिन्न भावों के
लिए , जहाँ उनकी संयुक्त लंबाई है , यह बचाता है:nul
l - (3 * n) - u - 10 ( + brackets removed )


1

एक सूची का उपयोग करें

एक सूची को पैरामीटर के रूप में घोषित करें और .append() orमूल्य को स्टोर करने के लिए उपयोग करें: में
lambda s:s.lower()+s.lower()[::-1]
बदल जाता है
lambda s,l=[]:l.append(s.lower())or l[-1]+l[-1][::-1]

अक्षर गणना:

,l=[]5 वर्ण
l.append()or13 वर्ण
l[-1]प्रत्येक वर्ण के लिए 5 वर्ण

ब्रेक - ईवन

अतिरिक्त वर्ण की मात्रा है:
uses*(5-length) + 18 + length
पिछले उदाहरण में कथन s.lower()9 वर्णों का है और 2 बार उपयोग किया जाता है, इस तकनीक को लागू करने में 19 वर्ण जोड़े गए हैं। यदि यह 7 बार उपयोग किया गया था, तो 1 वर्ण की कमी होगी।
इस तकनीक का कम से कम उपयोग करने लायक है
min_uses = (18+length)/(length-5)

तेजी

  • थोड़ी कम लागत पर एक नया काम करने की अनुमति दें (सूची पहले से ही घोषित है)
  • एक है listवस्तु इतनी [0], .pop(), [x:y]और अन्य सूची कार्यों चाल के लिए इस्तेमाल किया जा सकता है। अत्यधिक स्थितिजन्य

downsides

  • उच्च प्रारंभिक लागत
  • उच्च उपयोग लागत
  • केवल लंबाई से अधिक के उपयोग के लिए काम करता है 5

शब्दकोश का उपयोग करें

धन्यवाद @Zgarb
ऊपर के रूप में एक ही विचार एक डिक्लेयर के रूप में एक डिक्लेयर के रूप में घोषित करता है और .setdefault()मूल्य को स्टोर करने (और वापस करने) के लिए उपयोग
lambda s:s.lower()+s.lower()[::-1]
करता है : समकक्ष के
lambda s,d={}:d.setdefault(0,s.lower())+d[0][::-1]
विपरीत, नोट में बदल जाता listहै,setdefault असाइन किए गए मान को लौटाता है।

अक्षर गणना:

,d={}प्रत्येक वर्ण के लिए 5 वर्ण
d.setdefault(k,)16 वर्ण
d[k]4 वर्ण

ब्रेक - ईवन

अतिरिक्त वर्ण की मात्रा है:
(uses-1)*(4-length) + 21
पिछले उदाहरण में कथन s.lower()9 वर्णों का है और 2 बार उपयोग किया जाता है, इस तकनीक को लागू करने में 16 वर्ण जोड़े गए हैं। यदि यह 7 बार उपयोग किया गया था, तो 1 वर्ण की कमी होगी।
इस तकनीक का कम से कम उपयोग करने लायक है
min_uses = 1-21/(4-length)

तेजी / Downsides

  • मूल रूप से सूची के समान ही
  • केवल लंबाई से अधिक के उपयोग के लिए काम करता है 4

अन्य बातें

  • यदि यह तकनीक चरित्र में कमी के लायक है, तो lambdaसंभवतः गिराया जा सकता है और फ़ंक्शन को फिर से लिखा जा सकता है def/input को एक छोटे कार्यक्रम के ।
  • जैसा कि @FlipTack ने बताया, लिस्ट और डिक्टेट फ़ंक्शन कॉल के बीच KEEPT हैं , जबकि यह ज्यादातर परेशान करेगा, इसका उपयोग पुनरावर्ती कॉल पर किया जा सकता है। फिर से अत्यधिक स्थितिजन्य
  • शब्दकोश हमेशा सूची से छोटा होगा।

3
फ़ंक्शन सबमिशन को एक से अधिक बार उपयोग करने योग्य होना चाहिए। वर्तमान में यह एक ही सूची का उपयोग करता है जब लैंबडा चलाया जाता है, जो बाद के रनों पर चीजों को गड़बड़ कर सकता है।
FlipTack

@ ब्याज से बाहर, क्या आप मेटा जैसे स्रोत को जोड़ने का मन करेंगे? मुझे लगता है कि नियम मुझे पता है कि कुछ चाल पर कुछ प्रभाव हो सकता है।
JAD


मुझे लगता है कि आप एक शब्दकोश के साथ बेहतर कर सकते हैं: lambda s,d={}:d.setdefault(0,s.lower())+d[0][::-1]यह भी पुन: प्रयोज्य है।
जर्गर्ब

आप list.extendएक साथ कई तत्वों को जोड़ने के लिए उपयोग कर सकते हैं , जो list.appendकई बार उपयोग करने से कम होगा ।
mbomb007

0

वैरिएबल सेट करने के लिए उपयोग करें और ऑपरेशन के बाद डेटा को वापस करें जैसे:

add = lambda x, y: exec("x+=y")

वैकल्पिक रूप से: {add = lambda x, y: [x.append (x [0] + y), x.reverse (), x.pop ()]}
डायलन एलियट

0

सूची की समझ

यह एक अंतिम उपाय है, क्योंकि यह बहुत ही अस्वास्थ्यकर है, लेकिन आप एक लंबोदर
[<expression> for <variable> in <value>]
में एक चर को सेट करने के लिए कर सकते हैं । मूल रूप से इस पद्धति के बारे में एकमात्र अच्छी बात यह है कि आंतरिक अभिव्यक्ति पठनीय रह सकती है, जो कि स्पष्ट रूप से आपकी चिंता का विषय है जब गोल्फिंग।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.