Biorąc pod uwagę ten fragment kodu:
from os import walk
files = []
for (dirpath, _, filenames) in walk(mydir):
# more code that modifies files
if len(files) == 0: # <-- C1801
return None
Pylint zaniepokoił mnie tą wiadomością dotyczącą wiersza z instrukcją if:
[pylint] C1801: Nie należy używać
len(SEQUENCE)
jako wartości warunku
Zasada C1801 na pierwszy rzut oka nie brzmiała dla mnie zbyt rozsądnie, a definicja w podręczniku nie wyjaśnia, dlaczego jest to problem. W rzeczywistości wręcz nazywa to niewłaściwym użyciem .
len-as-condition (C1801) : Nie należy używać
len(SEQUENCE)
jako wartości warunku Używane, gdy Pylint wykryje nieprawidłowe użycie len (sekwencji) w warunkach wewnętrznych.
Moje próby wyszukiwania również nie dały mi głębszego wyjaśnienia. Rozumiem, że właściwość długości sekwencji może być leniwie oceniana i __len__
może być zaprogramowana tak, aby wywoływała skutki uboczne, ale wątpliwe jest, czy sama ta jest wystarczająco problematyczna, aby Pylint mógł nazwać takie użycie niepoprawnym. Dlatego zanim skonfiguruję mój projekt tak, aby ignorował regułę, chciałbym wiedzieć, czy coś mi brakuje w moim rozumowaniu.
Kiedy użycie len(SEQ)
jako warunku jest problematyczne? Jakie główne sytuacje próbuje uniknąć Pylint z C1801?
źródło
if files:
lubif not files:
len
nie zna kontekstu, w którym jest wywoływany, więc jeśli obliczenie długości oznacza przejście całej sekwencji, musi; nie wie, że wynik jest właśnie porównywany z 0. Obliczenie wartości logicznej może zostać zatrzymane po zobaczeniu pierwszego elementu, niezależnie od tego, jak długo faktycznie trwa sekwencja. Myślę jednak, że pylint jest tu nieco opiniotwórczy; Nie mogę wymyślić żadnej sytuacji, w której użycie byłoby niewłaściwelen
, tylko że jest to gorsza opcja niż alternatywa.Odpowiedzi:
Nie jest to zbyt problematyczne w użyciu
len(SEQUENCE)
- choć może nie być tak wydajne (patrz komentarz chepnera ). Niezależnie od tego, Pylint sprawdza kod pod kątem zgodności z przewodnikiem stylu PEP 8, który to stwierdzaJako sporadyczny programista Python, który porusza się między językami, uważam, że
len(SEQUENCE)
konstrukcja jest bardziej czytelna i wyraźna („Jawna jest lepsza niż niejawna”). Jednak użycie faktu, że pusta sekwencja jest ewaluowanaFalse
w kontekście logicznym, jest uważane za bardziej „pytoniczne”.źródło
if len(fnmatch.filter(os.listdir(os.getcwd()), 'f_*')):
if next(iter(...), None) is not None:
(jeśli sekwencja nie może zawieraćNone
). To długo, ale teżlen(fnmatch...)
jest długie; oba muszą być podzielone.len(s) == 0
jest lepszy, jest to, że można go uogólniać dla innych typów sekwencji. Na przykładpandas.Series
i tablice numpy.if not s:
nie jest z drugiej strony, w takim przypadku należałoby zastosować osobną ocenę dla wszystkich możliwych typów obiektów podobnych do tablic (tjpd.DataFrame.empty
.).of collections.abc
klasa nie określa__bool__
metody. Innymi słowy, jak mogę się upewnić, że mogę z niego korzystać,bool(seq)
jeśli wiem, że to jestcollections.abc.Collection
? Moreso, niektóre biblioteki deklarują, że zabronione jest sprawdzaniebool(collection)
ich klas.Zauważ, że użycie len (seq) jest w rzeczywistości wymagane (zamiast po prostu sprawdzania wartości bool seq) podczas korzystania z tablic NumPy.
powoduje wyjątek: ValueError: Wartość prawdy tablicy z więcej niż jednym elementem jest niejednoznaczna. Użyj a.any () lub a.all ()
Dlatego w przypadku kodu, który korzysta zarówno z list Pythona, jak i tablic NumPy, komunikat C1801 jest mniej niż pomocny.
źródło
Był to problem z pylintem i nie jest już uważany
len(x) == 0
za niepoprawny.Nie powinieneś używać goły
len(x)
jako warunek. Porównywanielen(x)
z wyraźną wartością, taką jakif len(x) == 0
of,if len(x) > 0
jest całkowicie w porządku i nie jest zabronione przez PEP 8.Od PEP 8 :
Pamiętaj, że jawne testowanie długości nie jest zabronione. Zen Pythona stwierdza:
W wyborze między
if not seq
iif not len(seq)
oba są niejawne, ale zachowanie jest inne. Aleif len(seq) == 0
lubif len(seq) > 0
są wyraźne porównania i w wielu kontekstach prawidłowe zachowanie.W pylint, PR 2815 naprawił ten błąd, po raz pierwszy zgłoszony jako problem 2684 . Będzie nadal narzekać
if len(seq)
, ale nie będzie już narzekaćif len(seq) > 0
. PR został scalony 2019-03-19, więc jeśli używasz pylint 2.4 (wydany 14.09.2019), nie powinieneś widzieć tego problemu.źródło
Pylint zawiódł w moim kodzie, a badania doprowadziły mnie do tego postu:
To był mój kod wcześniej:
To było po mojej poprawce kodu. Korzystając z
int()
attribute
, wydaje mi się, że jestem zadowolony z Pep8 / Pylint i nie wydaje się mieć negatywnego wpływu na mój kod:Moja poprawka
Po dodaniu
.__trunc__()
do sekwencji wydaje się, że zaspokoiła potrzebę.Nie widzę różnicy w zachowaniu, ale jeśli ktoś zna szczegóły, których mi brakuje, proszę dać mi znać.
źródło
__trunc__()
wyjścielen(seq)
, które (nieco redundantnie) obcina wartość długości do liczby całkowitej. To tylko „zwodzi” kłaczki, nie podając przyczyny. Czy sugestia w zaakceptowanej odpowiedzi nie działała dla Ciebie?this worked for me
nawet jeśli nie jest to całkowicie właściwe. Ale, aby wyjaśnić, nawet jeśli jest to zbędne, jeśli robisz porównanie len (seq) == 0, trunc nie powinien nic robić, ponieważ są już liczbami całkowitymi. dobrze?__trunc__()
nie robi nic znaczącego. Zauważ, że nie odnosiłem się do porównania jako zbędnego, ale do tej próby skracania długości. Ostrzeżenie znika tylko dlatego, że oczekuje tylko wyrażenia formylen(seq) == 0
. Uważam, że kłaczki w tym przypadku spodziewają się, żeif not dirnames and not filenames:
__bool__
funkcja nie jest zdefiniowana w sekwencji leżącej u podstaw.