E731 एक लैम्ब्डा अभिव्यक्ति प्रदान नहीं करते हैं, एक डीफ़ का उपयोग करें


193

जब भी मैं लैम्बडा एक्सप्रेशन का उपयोग करता हूं मुझे यह pep8 चेतावनी मिलती है। क्या लंबोदर अभिव्यक्तियों की सिफारिश नहीं की जाती है? यदि नहीं तो क्यों?


4
स्पष्टता के लिए, प्रश्न में एक स्वचालित जांच के लिए एक संदेश को संदर्भित किया जाता है flake8( flake8.pycqa.org )
rakslice

जवाबों:


230

PEP-8 में अनुशंसा आप में चल रहे हैं:

हमेशा एक असाइनमेंट स्टेटमेंट के बजाय एक डिफ स्टेटमेंट का उपयोग करें जो एक नाम के लिए सीधे लंबोदर अभिव्यक्ति को बांधता है।

हाँ:

def f(x): return 2*x 

नहीं:

f = lambda x: 2*x 

पहले रूप का मतलब है कि परिणामी फ़ंक्शन ऑब्जेक्ट का नाम विशेष रूप से जेनेरिक '<lambda>' के बजाय 'f' है। यह सामान्य रूप से ट्रेसबैक और स्ट्रिंग अभ्यावेदन के लिए अधिक उपयोगी है। असाइनमेंट स्टेटमेंट का उपयोग एकमात्र लाभ को समाप्त करता है एक लैम्ब्डा अभिव्यक्ति एक स्पष्ट डीफ़ स्टेटमेंट (यानी कि यह एक बड़ी अभिव्यक्ति के अंदर एम्बेड किया जा सकता है) पर पेश कर सकता है

नाम के लिए लंबोदर को सौंपना मूल रूप से सिर्फ def- और सामान्य रूप से कार्यक्षमता को डुप्लिकेट करता है , भ्रम से बचने और स्पष्टता बढ़ाने के लिए कुछ एक ही तरीका करना सबसे अच्छा है।

लैम्ब्डा के लिए वैध उपयोग का मामला वह है जहाँ आप बिना असाइन किए किसी फ़ंक्शन का उपयोग करना चाहते हैं, जैसे:

sorted(players, key=lambda player: player.rank)

सामान्य तौर पर, ऐसा करने के खिलाफ मुख्य तर्क यह है कि defबयानों के परिणामस्वरूप कोड की अधिक लाइनें होंगी। उस पर मेरी मुख्य प्रतिक्रिया होगी: हाँ, और यह ठीक है। जब तक आप कोड गोल्फिंग नहीं कर रहे हैं, लाइनों की संख्या को कम करना कुछ ऐसा नहीं है जो आपको करना चाहिए: लघु पर स्पष्ट के लिए जाएं।


5
मैं नहीं देखता कि यह कैसे बदतर है। ट्रेसबैक अभी भी गलत लाइन नंबर और स्रोत फ़ाइल को शामिल करने जा रहा है। कोई "f" कह सकता है, जबकि दूसरा "lambda" कहता है। हो सकता है कि लंबोदर त्रुटि को स्कैन करना आसान हो, क्योंकि यह एकल-वर्ण फ़ंक्शन नाम या खराब नाम वाला लंबा नाम नहीं है?
g33kz0r

4
@ g33kz0r ठीक है, निश्चित रूप से, यदि आप मानते हैं कि आपके बाकी कोड खराब गुणवत्ता वाले हैं, तो निम्नलिखित सम्मेलनों से आपको बहुत लाभ नहीं होगा। सामान्य तौर पर, नहीं, यह दुनिया का अंत नहीं है, लेकिन यह अभी भी एक बुरा विचार है।
गारेथ लेटी

39
यह उत्तर बहुत उपयोगी नहीं है, क्योंकि defPEP8 चेकर के माध्यम से उपयोग करने के सुझाए गए दृष्टिकोण को चलाने पर , आपको मिलता है E704 multiple statements on one line (def), और यदि आप इसे दो पंक्तियों में विभाजित करते हैं , तो आपको E301 expected 1 blank line, found 0: - /
एडम स्पियर्स

4
मैं मानता हूं कि इसका विभाजन होना चाहिए। मेरे बिंदु थे कि a) यह ऊपर दिए गए उत्तर कोड में विभाजित नहीं है, जिससे E704, और b) यदि आप इसे विभाजित करते हैं, तो आपको E301 से बचने के लिए इसके ऊपर एक बदसूरत खाली लाइन की आवश्यकता होगी।
एडम स्पियर्स

3
जब मैं शुद्ध फ़ंक्शन (कोई साइड इफेक्ट्स) पर जोर देना चाहता हूं, तो मैं लैम्ब्डा का उपयोग करता हूं, और कभी-कभी मुझे एक ही फ़ंक्शन को दो स्थानों पर उपयोग करना पड़ता है, अर्थात समूहबद्ध और एक साथ। इसलिए मैं इस सम्मेलन की उपेक्षा करता हूं।
मनु २

119

यहाँ कहानी है, मेरे पास एक साधारण मेमने का कार्य था जिसे मैं दो बार उपयोग कर रहा था।

a = map(lambda x : x + offset, simple_list)
b = map(lambda x : x + offset, another_simple_list)

यह सिर्फ प्रतिनिधित्व के लिए है, मुझे इसके विभिन्न संस्करणों में से कुछ का सामना करना पड़ा है।

अब, DRY चीजों को रखने के लिए, मैं इस आम मेमने का पुन: उपयोग करना शुरू करता हूं।

f = lambda x : x + offset
a = map(f, simple_list)
b = map(f, another_simple_list)

इस बिंदु पर मेरे कोड क्वालिटी चेकर को लैम्ब्डा के नामांकित फ़ंक्शन के बारे में शिकायत है, इसलिए मैं इसे एक फ़ंक्शन में परिवर्तित करता हूं।

def f(x):
    return x + offset
a = map(f, simple_list)
b = map(f, another_simple_list)

अब चेकर शिकायत करता है कि एक फ़ंक्शन को पहले और बाद में एक रिक्त लाइन द्वारा बाध्य किया जाना है।

def f(x):
    return x + offset

a = map(f, simple_list)
b = map(f, another_simple_list)

यहां अब हमारे पास मूल 2 लाइनों के बजाय कोड की 6 पंक्तियां हैं, जिनमें पठनीयता में कोई वृद्धि नहीं है और न ही पायथोनिक होने में कोई वृद्धि है। इस बिंदु पर कोड चेकर को कार्य के बारे में शिकायत होती है कि उसके पास डॉकस्ट्रिंग नहीं है।

मेरे विचार में इस नियम को बेहतर तरीके से टाला और तोड़ा जाता है जब यह समझ में आता है, अपने फैसले का उपयोग करें।


13
a = [x + offset for x in simple_list]। कोई जरूरत नहीं है mapऔर lambdaयहाँ का उपयोग करने के लिए ।
जॉर्जी

8
@Georgy मेरा मानना ​​है कि बिंदु x + offsetको एक अमूर्त स्थान पर स्थानांतरित करना था जिसे कोड की एक से अधिक लाइन को बदले बिना अपडेट किया जा सकता है। जैसा कि आपने उल्लेख किया है, सूची बोध के साथ, आपको अभी भी कोड की दो पंक्तियों की आवश्यकता होगी जो निहित हैं x + offsetवे अभी सूची समझ में होंगे। जैसा कि लेखक चाहते थे, उन्हें बाहर खींचने के लिए आपको defया की आवश्यकता होगी lambda
जूलियन

1
@ जूलियन इसके अलावा defऔर lambdaएक भी functionalools.partial का उपयोग कर सकता है : f = partial(operator.add, offset)और फिर a = list(map(f, simple_list))
जार्ज

व्हाट अबाउट def f(x): return x + offset (यानी, एक लाइन पर परिभाषित एक सरल कार्य)? कम से कम flake8 के साथ मुझे रिक्त लाइनों के बारे में शिकायत नहीं मिलती है।
DocOc

1
@ जूलियन कुछ मामलों में आप एक नेस्टेड कॉम्प्रिहेंशन का उपयोग कर सकते हैं:a, b = [[x + offset for x lst] for lst in (simple_list, another_simple_list)]
wjandrea

24

लेटवेयर पूरी तरह से सही है: मूल रूप से PEP-8 चाहता है कि आप चीजों से बचें

f = lambda x: 2 * x

और इसके बजाय उपयोग करें

def f(x):
    return 2 * x

हालाँकि, जैसा कि हाल ही के एक बगरेपोर्ट (अगस्त 2014) में दिया गया है, इस तरह के बयान अब निम्नलिखित हैं:

a.f = lambda x: 2 * x
a["f"] = lambda x: 2 * x

चूंकि मेरे PEP-8 चेकर इसे अभी तक सही तरीके से लागू नहीं करते हैं, इसलिए मैंने E731 को फिलहाल बंद कर दिया।


8
उपयोग करते समय भी def, PEP8 चेकर के साथ शिकायत की जाती है E301 expected 1 blank line, found 0, इसलिए आपको इसके पहले एक बदसूरत खाली लाइन जोड़ना होगा।
एडम स्पाइर्स

1

मुझे एक ऐसी स्थिति का भी सामना करना पड़ा जिसमें एक डिफ (ined) फ़ंक्शन का उपयोग करना असंभव था।

class SomeClass(object):
  # pep-8 does not allow this
  f = lambda x: x + 1  # NOQA

  def not_reachable(self, x):
    return x + 1

  @staticmethod
  def also_not_reachable(x):
    return x + 1

  @classmethod
  def also_not_reachable(cls, x):
    return x + 1

  some_mapping = {
      'object1': {'name': "Object 1", 'func': f},
      'object2': {'name': "Object 2", 'func': some_other_func},
  }

इस मामले में, मैं वास्तव में एक मैपिंग करना चाहता था जो वर्ग से संबंधित हो। मानचित्रण में कुछ वस्तुओं को समान कार्य की आवश्यकता होती है। कक्षा के बाहर नामांकित समारोह रखना अशुभ होगा। मुझे क्लास बॉडी के अंदर से किसी विधि (staticmethod, classmethod या normal) को संदर्भित करने का कोई तरीका नहीं मिला है। कोड चलने पर SomeClass अभी तक मौजूद नहीं है। इसलिए कक्षा से इसका जिक्र संभव नहीं है।


आप also_not_reachableमैपिंग परिभाषा में उल्लेख कर सकते हैंSomeClass.also_not_reachable
23

1
मुझे नहीं पता कि आप यहाँ क्या बनाने की कोशिश कर रहे हैं। आपके प्रत्येक फ़ंक्शन का नाम fमेरे लिए 2.7 और 3.5 दोनों में समान है
एरिक

नहीं, मेमने के कार्य को छोड़कर सभी कार्य, कक्षा निकाय के भीतर से उपलब्ध नहीं हैं। आपको एक गुण मिलेगा: टाइप करें ऑब्जेक्ट 'SomeClass' में कोई विशेषता नहीं है '...' यदि आप some_mapping ऑब्जेक्ट में से किसी एक फ़ंक्शन तक पहुंचने का प्रयास करते हैं।
सिम

3
@simP वे सभी पूरी तरह से सुलभ हैं। साथ लोगों को @staticmethodऔर @classmethodएक वस्तु की जरूरत नहीं है, बस SomeClass.also_not_reachable(हालांकि वे विशिष्ट नामों की आवश्यकता)। यदि आपको उन्हें कक्षा के तरीकों से उपयोग करने की आवश्यकता हैself.also_not_reachable
ababak

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