Considerando este trecho de código:
from os import walk
files = []
for (dirpath, _, filenames) in walk(mydir):
# more code that modifies files
if len(files) == 0: # <-- C1801
return None
Fiquei alarmado com Pylint com esta mensagem sobre a linha com a instrução if:
[pylint] C1801: Não use
len(SEQUENCE)
como valor de condição
A regra C1801, à primeira vista, não me pareceu muito razoável, e a definição no guia de referência não explica por que isso é um problema. De fato, ele chama de uso incorreto .
len como condição (C1801) : não use
len(SEQUENCE)
como valor de condição Usado quando o Pylint detecta o uso incorreto de len (sequência) dentro das condições.
Minhas tentativas de pesquisa também falharam em me fornecer uma explicação mais profunda. Entendo que a propriedade de comprimento de uma sequência pode ser avaliada preguiçosamente e que __len__
pode ser programada para ter efeitos colaterais, mas é questionável se isso é problemático o suficiente para que Pylint chame esse uso de incorreto. Portanto, antes de simplesmente configurar meu projeto para ignorar a regra, gostaria de saber se estou perdendo alguma coisa no meu raciocínio.
Quando é len(SEQ)
problemático o uso como valor de condição? Que situações principais a Pylint está tentando evitar com o C1801?
fonte
if files:
ouif not files:
len
não conhece o contexto em que é chamado; portanto, se calcular o comprimento significa atravessar a sequência inteira, ele deve; ele não sabe que o resultado está sendo comparado a 0. A computação do valor booleano pode parar depois que ele vê o primeiro elemento, independentemente de quanto tempo a sequência realmente é. Eu acho que o pylint está sendo um pouco opinativo aqui; Não consigo pensar em nenhuma situação em que seja errado usarlen
, apenas que é uma opção pior que a alternativa.Respostas:
Não é realmente problemático de usar
len(SEQUENCE)
- embora possa não ser tão eficiente (veja o comentário de chepner ). Independentemente disso, a Pylint verifica o código quanto à conformidade com o guia de estilo do PEP 8, que afirma queComo programador ocasional em Python, que alterna entre linguagens, consideraria a
len(SEQUENCE)
construção mais legível e explícita (“Explícito é melhor que implícito”). No entanto, o uso do fato de que uma sequência vazia é avaliadaFalse
em um contexto booleano é considerado mais "pitônico".fonte
if len(fnmatch.filter(os.listdir(os.getcwd()), 'f_*')):
if next(iter(...), None) is not None:
(se a sequência não puder conterNone
). Isso é longo, maslen(fnmatch...)
também é longo; ambos precisam ser divididos.len(s) == 0
é superior na minha opinião é que ele é generalizável para outros tipos de sequências. Por exemplo,pandas.Series
e matrizes numpy.if not s:
não está por outro lado e, nesse caso, você precisaria usar uma avaliação separada para todos os tipos possíveis de objetos semelhantes a matrizes (ou sejapd.DataFrame.empty
).of collections.abc
classe declara o__bool__
método. Em outras palavras, como posso ter certeza de que posso usarbool(seq)
se souber que é umcollections.abc.Collection
? Além disso, algumas bibliotecas declaram que é proibido verificarbool(collection)
suas classes.Observe que o uso de len (seq) é de fato necessário (em vez de apenas verificar o valor bool de seq) ao usar matrizes NumPy.
resulta em uma exceção: ValueError: o valor verdadeiro de uma matriz com mais de um elemento é ambíguo. Use a.any () ou a.all ()
E, portanto, para o código que usa listas Python e matrizes NumPy, a mensagem C1801 é menos que útil.
fonte
Esse foi um problema no pylint e não é mais considerado
len(x) == 0
incorreto.Você não deve usar o bare
len(x)
como condição. A comparaçãolen(x)
com um valor explícito, comoif len(x) == 0
de,if len(x) > 0
é totalmente adequada e não é proibida pelo PEP 8.Do PEP 8 :
Observe que testar explicitamente o comprimento não é proibido. O Zen do Python afirma:
Na escolha entre
if not seq
eif not len(seq)
, ambos estão implícitos, mas o comportamento é diferente. Masif len(seq) == 0
ouif len(seq) > 0
são comparações explícitas e, em muitos contextos, o comportamento correto.Em pylint, o PR 2815 corrigiu esse bug, relatado pela primeira vez como problema 2684 . Ele continuará reclamando
if len(seq)
, mas não reclamará maisif len(seq) > 0
. O PR foi mesclado 19/03/2019, portanto, se você estiver usando o pylint 2.4 (lançado em 2019-09-14), não deverá encontrar esse problema.fonte
Pylint estava falhando no meu código e a pesquisa me levou a este post:
Este foi o meu código antes:
Isso foi depois da minha correção de código. Ao usar o
int()
attribute
, eu pareço ter satisfeito o Pep8 / Pylint e não parece ter um impacto negativo no meu código:My Fix
Ao adicionar
.__trunc__()
à sequência, parece ter resolvido a necessidade.Não vejo diferença no comportamento, mas se alguém souber de detalhes que estão faltando, entre em contato.
fonte
__trunc__()
a saída delen(seq)
, que (de certa forma redundante) trunca o valor do comprimento para um número inteiro. Ele apenas "finge" o fiapo sem abordar o motivo por trás dele. A sugestão na resposta aceita não funcionou para você?this worked for me
, mesmo que não seja totalmente apropriado. Mas, para esclarecer, mesmo que seja redundante, se você estiver fazendo uma comparação len (seq) == 0, o trunc não deve ter que fazer nada, pois já são números inteiros. certo?__trunc__()
não faz nada significativo. Observe que não me referi à comparação como sendo redundante, mas a esta tentativa de truncar o comprimento. O aviso desaparece apenas porque espera apenas uma expressão do formuláriolen(seq) == 0
. Acredito que o fiapo nesse caso esperaria que você substituísse a instrução if pela seguinte:if not dirnames and not filenames:
__bool__
função não estiver definida na sequência subjacente.