Mempertimbangkan cuplikan kode ini:
from os import walk
files = []
for (dirpath, _, filenames) in walk(mydir):
# more code that modifies files
if len(files) == 0: # <-- C1801
return None
Saya terkejut oleh Pylint dengan pesan ini mengenai baris dengan pernyataan if:
[pylint] C1801: Jangan gunakan
len(SEQUENCE)
sebagai nilai kondisi
Aturan C1801, pada pandangan pertama, tidak terdengar sangat masuk akal bagi saya, dan definisi pada panduan referensi tidak menjelaskan mengapa ini menjadi masalah. Bahkan, itu benar-benar menyebutnya penggunaan yang salah .
len-as-condition (C1801) : Jangan gunakan
len(SEQUENCE)
sebagai nilai kondisi Digunakan ketika Pylint mendeteksi penggunaan salah len (urutan) di dalam kondisi.
Upaya pencarian saya juga gagal memberi saya penjelasan yang lebih dalam. Saya mengerti bahwa properti panjang urutan dapat dievaluasi dengan malas, dan yang __len__
dapat diprogram untuk memiliki efek samping, tetapi dipertanyakan apakah itu saja yang cukup bermasalah bagi Pylint untuk menyebut penggunaan seperti itu salah. Oleh karena itu, sebelum saya cukup mengkonfigurasi proyek saya untuk mengabaikan aturan, saya ingin tahu apakah saya kehilangan sesuatu dalam alasan saya.
Kapan penggunaan len(SEQ)
sebagai nilai kondisi bermasalah? Situasi utama apa yang berusaha dihindari oleh Pylint dengan C1801?
sumber
if files:
atauif not files:
len
tidak tahu konteks di mana ia dipanggil, jadi jika menghitung panjang berarti melintasi seluruh urutan, ia harus; tidak tahu bahwa hasilnya hanya dibandingkan dengan 0. Menghitung nilai boolean dapat berhenti setelah melihat elemen pertama, terlepas dari berapa lama urutan sebenarnya. Saya pikir pylint sedang sedikit berpendapat di sini, meskipun; Saya tidak bisa memikirkan situasi di mana itu salah untuk digunakanlen
, hanya saja itu pilihan yang lebih buruk daripada alternatifnya.Jawaban:
Ini tidak benar - benar bermasalah untuk digunakan
len(SEQUENCE)
- meskipun mungkin tidak seefisien (lihat komentar chepner ). Apapun, Pylint memeriksa kode untuk kepatuhan dengan panduan gaya PEP 8 yang menyatakan ituSebagai programmer Python sesekali, yang berpindah antar bahasa, saya akan menganggap
len(SEQUENCE)
konstruk lebih mudah dibaca dan eksplisit ("Eksplisit lebih baik daripada implisit"). Namun, menggunakan fakta bahwa urutan kosong mengevaluasiFalse
dalam konteks Boolean dianggap lebih "Pythonic".sumber
if len(fnmatch.filter(os.listdir(os.getcwd()), 'f_*')):
if next(iter(...), None) is not None:
(jika urutannya tidak mengandungNone
). Itu panjang, tapilen(fnmatch...)
terlalu panjang; keduanya perlu dibagi.len(s) == 0
itu lebih unggul menurut saya adalah bahwa itu dapat digeneralisasi untuk jenis urutan lainnya. Misalnya,pandas.Series
dan array numpy.if not s:
tidak di sisi lain, dan dalam hal ini Anda perlu menggunakan evaluasi terpisah untuk semua jenis objek seperti array yang mungkin (yaitupd.DataFrame.empty
).of collections.abc
kelas yang menyatakan__bool__
metode. Dengan kata lain, bagaimana saya bisa yakin bahwa saya dapat menggunakanbool(seq)
jika saya tahu itu adalahcollections.abc.Collection
? Selain itu, beberapa perpustakaan menyatakan bahwa dilarang memeriksabool(collection)
kelas mereka.Perhatikan bahwa penggunaan len (seq) sebenarnya diperlukan (alih-alih hanya memeriksa nilai bool dari seq) saat menggunakan array NumPy.
menghasilkan pengecualian: ValueError: Nilai kebenaran array dengan lebih dari satu elemen ambigu. Gunakan a.any () atau a.all ()
Dan karenanya untuk kode yang menggunakan daftar Python dan array NumPy, pesan C1801 kurang membantu.
sumber
Ini merupakan masalah di pylint, dan itu tidak lagi dianggap
len(x) == 0
sebagai salah.Anda tidak harus menggunakan telanjang
len(x)
sebagai syarat. Membandingkanlen(x)
terhadap nilai eksplisit, sepertiif len(x) == 0
dariif len(x) > 0
benar-benar baik-baik saja dan tidak dilarang oleh PEP 8.Dari PEP 8 :
Perhatikan bahwa pengujian secara eksplisit untuk panjang tidak dilarang. The Zen of Python menyatakan:
Dalam pilihan antara
if not seq
danif not len(seq)
, keduanya implisit tetapi perilaku berbeda. Tetapiif len(seq) == 0
atauif len(seq) > 0
apakah perbandingan eksplisit dan dalam banyak konteks perilaku yang benar.Dalam pylint, PR 2815 telah memperbaiki bug ini, pertama kali dilaporkan sebagai masalah 2684 . Itu akan terus mengeluh
if len(seq)
, tetapi tidak akan lagi mengeluhif len(seq) > 0
. PR digabung 2019-03-19 jadi jika Anda menggunakan pylint 2.4 (dirilis 2019-09-14) Anda seharusnya tidak melihat masalah ini.sumber
Pylint gagal untuk kode saya dan penelitian membawa saya ke pos ini:
Ini adalah kode saya sebelumnya:
Ini setelah perbaikan kode saya. Dengan menggunakan
int()
attribute
, saya tampaknya telah memenuhi Pep8 / Pylint dan tampaknya tidak memiliki dampak negatif pada kode saya:Perbaiki saya
Dengan menambahkan
.__trunc__()
urutan itu tampaknya telah memenuhi kebutuhan.Saya tidak melihat perbedaan dalam perilaku, tetapi jika ada yang tahu secara spesifik bahwa saya hilang, tolong beri tahu saya.
sumber
__trunc__()
output darilen(seq)
, yang (agak berlebihan) memotong nilai panjang ke integer. Itu hanya "membohongi" serat itu tanpa menyinggung alasan di baliknya. Tidakkah saran dalam jawaban yang diterima bekerja untuk Anda?this worked for me
-olah itu tidak sepenuhnya sesuai. Tetapi, untuk memperjelas bahkan jika itu berlebihan jika Anda melakukan perbandingan len (seq) == 0, trunc seharusnya tidak perlu melakukan apa-apa karena mereka sudah bilangan bulat. Baik?__trunc__()
tidak melakukan sesuatu yang berarti. Perhatikan bahwa saya tidak menyebut perbandingan sebagai berlebihan, tetapi untuk upaya memotong panjang. Peringatan hanya menghilang karena hanya mengharapkan ekspresi formulirlen(seq) == 0
. Saya percaya bahwa serat dalam hal ini akan mengharapkan Anda untuk mengganti pernyataan if dengan yang berikut:if not dirnames and not filenames:
__bool__
fungsi tersebut tidak didefinisikan dalam urutan yang mendasarinya.