Pylint द्वारा गलत माने जाने वाले हालत मूल्यों में len (SEQUENCE) का उपयोग क्यों किया जाता है?


211

इस कोड को ध्यान में रखते हुए स्निपेट:

from os import walk

files = []
for (dirpath, _, filenames) in walk(mydir):
    # more code that modifies files
if len(files) == 0: # <-- C1801
    return None

यदि इस कथन के साथ लाइन के बारे में इस संदेश के साथ मुझे Pylint ने चिंतित किया:

[pylint] C1801: len(SEQUENCE)शर्त मूल्य के रूप में उपयोग न करें

नियम C1801, पहली नज़र में, मेरे लिए बहुत उचित नहीं लगा, और संदर्भ गाइड पर परिभाषा यह नहीं बताती है कि यह एक समस्या क्यों है। वास्तव में, यह सर्वथा इसे गलत उपयोग कहता है ।

len-as-condition (C1801) : जब Pylint, लीन (अनुक्रम) का गलत इस्तेमाल करता है, तो कंडीशन वैल्यू के रूप में इस्तेमाल न करें len(SEQUENCE)

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

जब len(SEQ)एक स्थिति मूल्य समस्याग्रस्त के रूप में उपयोग किया जाता है? पाइल्ट C1801 से बचने के लिए किन प्रमुख स्थितियों में प्रयास कर रहा है?


9
क्योंकि आप सीधे अनुक्रम की सत्यता का मूल्यांकन कर सकते हैं। pylint चाहता है कि आप करें if files:याif not files:
पैट्रिक हॉग

38
lenउस संदर्भ को नहीं जानता जिसमें इसे कहा जाता है, इसलिए यदि लंबाई की गणना का अर्थ है पूरे अनुक्रम का पता लगाना, तो यह अवश्य होगा; यह नहीं पता है कि परिणाम की तुलना सिर्फ 0. से की जा रही है। बूलियन मान को कम करना तब बंद हो सकता है जब यह पहला तत्व देखता है, वास्तव में यह क्रम कितना लंबा है, इसकी परवाह किए बिना। मुझे लगता है कि pylint यहाँ एक बालक राय है, हालांकि; मैं ऐसी किसी भी स्थिति के बारे में नहीं सोच सकता जहाँ इसका इस्तेमाल करना गलत है len, बस यह विकल्प से भी बदतर विकल्प है।
शेपनर

2
@ E_net4 मुझे लगता है कि PEP-8 शायद शुरू करने की जगह है।
पैट्रिक हॉग


6
SEQUENCES को C ++ imo की तरह 'खाली ()' या 'isempty ()' की आवश्यकता होती है।
जॉर्डन

जवाबों:


281

जब len(SEQ)एक शर्त मूल्य समस्याग्रस्त के रूप में उपयोग किया जाता है? पाइल्ट C1801 से बचने के लिए किन प्रमुख स्थितियों में प्रयास कर रहा है?

यह वास्तव में उपयोग करने के लिए समस्याग्रस्त नहीं है len(SEQUENCE)- हालांकि यह उतना कुशल नहीं हो सकता है ( चेपनर की टिप्पणी देखें )। बावजूद, Pylint PEP 8 स्टाइल गाइड के अनुपालन के लिए कोड की जांच करता है जो बताता है कि

अनुक्रमों के लिए, (स्ट्रिंग्स, सूचियों, ट्यूपल्स), इस तथ्य का उपयोग करें कि खाली क्रम झूठे हैं।

Yes: if not seq:
     if seq:

No:  if len(seq):
     if not len(seq):

एक सामयिक पायथन प्रोग्रामर के रूप में, जो भाषाओं के बीच फ़्लिट करता है, मैं len(SEQUENCE)निर्माण को अधिक पठनीय और स्पष्ट ("स्पष्ट बेहतर है तो निहित") माना जाएगा। हालांकि, इस तथ्य का उपयोग करते हुए कि Falseबूलियन संदर्भ में एक खाली अनुक्रम का मूल्यांकन अधिक "पाइथोनिक" माना जाता है।


इस काम को कैसे करें:if len(fnmatch.filter(os.listdir(os.getcwd()), 'f_*')):
मारीचसाना

@ मारीचसाना मुझे लगता है कि जैसी चीजें (सैद्धांतिक रूप से) लिखी जा सकती हैं if next(iter(...), None) is not None:(यदि अनुक्रम शामिल नहीं हो सकता है None)। यह लंबा है, लेकिनlen(fnmatch...) लंबा भी है; दोनों को विभाजित करने की आवश्यकता है।
किरिल ब्यूलगिन

13
मैं एक समसामयिक पायथन उपयोगकर्ता भी हूं और अक्सर मुझे यह आभास होता है कि "पायथोनिक तरीका" अपनी ही अस्पष्टता में उलझ गया है।
luqo33

3
बस एक सामान्य प्रश्न, क्या इन पीईपी सिफारिशों को संशोधित किया जा सकता है? len(s) == 0मेरे विचार में श्रेष्ठ होने का एक और कारण यह है कि यह अन्य प्रकार के दृश्यों के लिए सामान्य है। उदाहरण के लिए, pandas.Seriesऔर सुन्न सरणियाँ। if not s:दूसरी तरफ नहीं है, और उस मामले में आपको सभी संभावित प्रकारों के लिए एक अलग मूल्यांकन का उपयोग करने की आवश्यकता होगी-जैसे ऑब्जेक्ट (यानीpd.DataFrame.empty ) के ।
Marses

2
वैसे, कोई भी of collections.abcवर्ग __bool__विधि नहीं बताता है। दूसरे शब्दों में, मैं यह कैसे सुनिश्चित कर सकता हूं कि bool(seq)अगर मैं जानता हूं कि मैं इसका उपयोग कर सकता हूं collections.abc.Collection? मोरेसो, कुछ पुस्तकालय घोषित करते हैं कि bool(collection)उनकी कक्षाओं के लिए जाँच करना मना है ।
Eir Nym

42

ध्यान दें कि NumPy सरणियों का उपयोग करते समय लेन (seq) का उपयोग वास्तव में आवश्यक है (केवल seq के बूल मूल्य की जाँच के बजाय)।

a = numpy.array(range(10))
if a:
    print "a is not empty"

एक अपवाद के परिणाम: ValueError: एक सरणी का सत्य मान एक से अधिक तत्वों के साथ अस्पष्ट है। A.any () या a.all () का उपयोग करें

और इसलिए कोड के लिए जो पायथन लिस्ट और न्यूमी सरणियों दोनों का उपयोग करता है, C1801 संदेश सहायक से कम है।


5
मैं आपके कथन से सहमत हूं। साथ मुद्दे # 1405 अब उठाया, मैं C1801 देखने की उम्मीद या तो कुछ उपयोगी करने के लिए सुधार या डिफ़ॉल्ट रूप से अक्षम।
E_net4

2
प्लस यह जाँच के लिए बेकार है कि क्या किसी अनुक्रम में तत्वों की संख्या है। यह केवल जाँच के लिए अच्छा है कि यह सबसे अच्छे मामलों में पूरी तरह से खाली है।
पाबोररे

1

यह पाइलिंट में एक मुद्दा था, और यह अब विचार नहीं करता है len(x) == 0 गलत ।

आपको एक शर्त के रूप में एक नंगे का उपयोग नहीं करना चाहिए len(x)। की तुलनाlen(x) में इस तरह के रूप में, एक स्पष्ट मूल्य के खिलाफ if len(x) == 0कीif len(x) > 0 पूरी तरह से ठीक है और नहीं पीईपी 8 द्वारा निषिद्ध है।

से पीईपी 8 :

# Correct:
if not seq:
if seq:

# Wrong:
if len(seq):
if not len(seq):

ध्यान दें कि लंबाई के लिए स्पष्ट रूप से परीक्षण निषिद्ध नहीं है। अजगर की जेन कहती है:

निहितार्थ की तुलना में स्पष्ट है।

के बीच की पसंद में if not seqऔर if not len(seq), दोनों निहित हैं लेकिन व्यवहार अलग है। लेकिन if len(seq) == 0याif len(seq) > 0 स्पष्ट तुलना और कई संदर्भों में सही व्यवहार हैं।

पाइलिंट में, पीआर 2815 ने इस बग को ठीक कर दिया है, पहले इसे 2684 जारी किया गया था । यह शिकायत करना जारी रखेगा if len(seq), लेकिन यह अब शिकायत नहीं करेगा if len(seq) > 0। PR को 2019-03-19 में विलय कर दिया गया था, इसलिए यदि आप pylint 2.4 (जारी 2019-09-14) का उपयोग कर रहे हैं, तो आपको यह समस्या नहीं देखनी चाहिए।


0

पाइलिंट मेरे कोड के लिए असफल हो रहा था और अनुसंधान ने मुझे इस पद तक पहुँचाया:

../filename.py:49:11: C1801: Do not use `len(SEQUENCE)` to determine if a sequence is empty (len-as-condition)
../filename.py:49:34: C1801: Do not use `len(SEQUENCE)` to determine if a sequence is empty (len-as-condition)

इससे पहले यह मेरा कोड था:

def list_empty_folders(directory):
"""The Module Has Been Build to list empty Mac Folders."""
for (fullpath, dirnames, filenames) in os.walk(directory):
    if len(dirnames) == 0 and len(filenames) == 0:
        print("Exists: {} : Absolute Path: {}".format(
            os.path.exists(fullpath), os.path.abspath(fullpath)))

यह मेरे कोड फिक्स के बाद था। का उपयोग करके int() attribute, मुझे लगता है कि Pep8 / Pylint संतुष्ट है और मेरे कोड पर नकारात्मक प्रभाव नहीं पड़ता है:

def list_empty_folders(directory):
"""The Module Has Been Build to list empty Mac Folders."""
for (fullpath, dirnames, filenames) in os.walk(directory):
    if len(dirnames).__trunc__() == 0 and len(filenames).__trunc__() == 0:
        print("Exists: {} : Absolute Path: {}".format(
            os.path.exists(fullpath), os.path.abspath(fullpath)))

मेरा फिक्स

.__trunc__()अनुक्रम में जोड़कर यह लगता है कि जरूरत को सुलझा लिया है।

मुझे व्यवहार में कोई अंतर नहीं दिखता है, लेकिन अगर किसी को पता है कि मुझे याद आ रही है, तो कृपया मुझे बताएं।


1
आप __trunc__()के आउटपुट पर कॉल कर रहे हैं len(seq), जो (कुछ हद तक) एक पूर्णांक के लिए लंबाई मान को छोटा करता है। यह केवल इसके पीछे के कारण को संबोधित किए बिना लिंट को "संकेत" देता है। क्या आपके लिए स्वीकृत उत्तर कार्य में सुझाव नहीं था?
E_net4

मेरे प्रयासों में नहीं। मैं अतिरेक को समझता हूं, लेकिन इसके बाद भी डेवलपर्स द्वारा github.com/PyCQA/pylint/issues/1405 & 2684 में इस मुद्दे को संबोधित किया गया है और मेरी समझ में विलय कर दिया गया है, यह एक मुद्दा नहीं होना चाहिए जब पाइलिंट चला रहा हो लेकिन मैं अपने पाइलिंट को अपडेट करने के बाद भी इस मुद्दे को देखता हूं। मैं बस साझा करना चाहता था, जैसे this worked for meकि यह पूरी तरह से उचित नहीं है। लेकिन, यह स्पष्ट करने के लिए कि क्या यह बेमानी है यदि आप एक लेन (seq) == 0 तुलना कर रहे हैं, तो ट्रंक को कुछ भी नहीं करना चाहिए क्योंकि वे पहले से ही पूर्णांक हैं। सही?
JayRizzo

1
वास्तव में, यह पहले से ही एक पूर्णांक है, और __trunc__()कुछ भी सार्थक नहीं करता है। ध्यान दें कि मैं तुलनात्मक रूप से निरर्थक होने के संदर्भ में नहीं था, लेकिन लंबाई को कम करने के इस प्रयास में। चेतावनी केवल गायब हो जाती है क्योंकि यह केवल फॉर्म की अभिव्यक्ति की उम्मीद करती है len(seq) == 0। मुझे विश्वास है कि इस मामले में एक प्रकार का वृक्ष आपको उम्मीद करेगा कि यदि आप निम्नलिखित कथन को प्रतिस्थापित करें:if not dirnames and not filenames:
E_net4 प्यारा नहीं है

यदि __bool__फ़ंक्शन अंतर्निहित अनुक्रम में परिभाषित नहीं किया गया है, तो सत्यता के परीक्षण के "हमेशा सच" होने के अनपेक्षित परिणाम होते हैं ।
एरिक एरोनिटी
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.