Teniendo en cuenta este fragmento 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
Pylint me alarmó con este mensaje con respecto a la línea con la declaración if:
[pylint] C1801: No utilizar
len(SEQUENCE)
como valor de condición
La regla C1801, a primera vista, no me pareció muy razonable, y la definición en la guía de referencia no explica por qué esto es un problema. De hecho, lo llama francamente un uso incorrecto .
len-as-condition (C1801) : no utilizar
len(SEQUENCE)
como valor de condición Se utiliza cuando Pylint detecta el uso incorrecto de len (secuencia) dentro de las condiciones.
Mis intentos de búsqueda tampoco han podido proporcionarme una explicación más profunda. Entiendo que la propiedad de longitud de una secuencia puede evaluarse perezosamente, y que __len__
se puede programar para que tenga efectos secundarios, pero es cuestionable si eso solo es lo suficientemente problemático como para que Pylint considere incorrecto dicho uso. Por lo tanto, antes de simplemente configurar mi proyecto para ignorar la regla, me gustaría saber si me falta algo en mi razonamiento.
¿Cuándo es len(SEQ)
problemático el uso de como valor de condición? ¿Qué situaciones principales intenta evitar Pylint con C1801?
fuente
if files:
oif not files:
len
no conoce el contexto en el que se llama, por lo que si calcular la longitud significa atravesar toda la secuencia, debe hacerlo; no sabe que el resultado solo se está comparando con 0. Calcular el valor booleano puede detenerse después de ver el primer elemento, independientemente de la duración de la secuencia. Sin embargo, creo que Pylint está siendo un poco obstinado aquí; No puedo pensar en ninguna situación en la que sea incorrecto usarlalen
, solo que es una opción peor que la alternativa.Respuestas:
No es realmente problemático de usar
len(SEQUENCE)
, aunque puede que no sea tan eficiente (vea el comentario de chepner ). Independientemente, Pylint verifica el código para el cumplimiento de la guía de estilo PEP 8 que establece queComo programador ocasional de Python, que pasa de un idioma a otro, consideraría que la
len(SEQUENCE)
construcción es más legible y explícita ("explícito es mejor que implícito"). Sin embargo, usar el hecho de que una secuencia vacía se evalúaFalse
en un contexto booleano se considera más "Pitónico".fuente
if len(fnmatch.filter(os.listdir(os.getcwd()), 'f_*')):
if next(iter(...), None) is not None:
(si la secuencia no puede contenerNone
). Eso es largo, pero también lolen(fnmatch...)
es; Ambos necesitan ser divididos.len(s) == 0
es superior en mi opinión es que es generalizable para otros tipos de secuencias. Por ejemplo,pandas.Series
y matrices numpy.if not s:
no es, por otro lado, y en ese caso necesitaría usar una evaluación separada para todos los tipos posibles de objetos tipo matriz (es decirpd.DataFrame.empty
).of collections.abc
clase establece el__bool__
método. En otras palabras, ¿cómo puedo estar seguro de que puedo usarbool(seq)
si sé que es uncollections.abc.Collection
? Más aún, algunas bibliotecas rechazan que esté prohibido verificarbool(collection)
sus clases.Tenga en cuenta que, de hecho, se requiere el uso de len (seq) (en lugar de simplemente verificar el valor bool de seq) cuando se usan matrices NumPy.
da como resultado una excepción: ValueError: el valor de verdad de una matriz con más de un elemento es ambiguo. Utilice a.any () o a.all ()
Y, por lo tanto, para el código que usa listas Python y matrices NumPy, el mensaje C1801 no es útil.
fuente
Este fue un problema en pylint, y ya no se considera
len(x) == 0
incorrecto.No debe usar un desnudo
len(x)
como condición. Compararlen(x)
con un valor explícito, comoif len(x) == 0
de,if len(x) > 0
está totalmente bien y no está prohibido por PEP 8.De PEP 8 :
Tenga en cuenta que no está prohibido probar explícitamente la longitud . El Zen de Python dice:
En la elección entre
if not seq
yif not len(seq)
, ambos son implícitos pero el comportamiento es diferente. Peroif len(seq) == 0
oif len(seq) > 0
son comparaciones explícitas y en muchos contextos el comportamiento correcto.En pylint, PR 2815 ha solucionado este error, primero informado como el problema 2684 . Continuará quejándose
if len(seq)
, pero ya no se quejaráif len(seq) > 0
. El PR se fusionó el 19/03/2019, por lo que si está utilizando pylint 2.4 (lanzado el 14/09/2019), no debería ver este problema.fuente
Pylint estaba fallando en mi código y la investigación me llevó a esta publicación:
Este era mi código antes:
Esto fue después de la reparación de mi código. Al usar el
int()
attribute
, parece que he satisfecho el Pep8 / Pylint y no parece tener un impacto negativo en mi código:Mi arreglo
Añadiendo
.__trunc__()
a la secuencia parece haber resuelto la necesidad.No veo una diferencia en el comportamiento, pero si alguien conoce los detalles que me faltan, hágamelo saber.
fuente
__trunc__()
a la salida delen(seq)
, que (algo redundantemente) trunca el valor de longitud a un entero. Solo "finta" la pelusa sin abordar la razón detrás de ella. ¿La sugerencia en la respuesta aceptada no funcionó para usted?this worked for me
incluso si no es del todo apropiado. Pero, para aclarar incluso si es redundante si está haciendo una comparación len (seq) == 0, trunc no debería tener que hacer nada ya que ya son enteros. ¿Derecha?__trunc__()
no hace nada significativo. Tenga en cuenta que no me referí a la comparación como redundante, sino a este intento de truncar la longitud. La advertencia solo desaparece porque solo espera una expresión del formulariolen(seq) == 0
. Creo que la pelusa en este caso esperaría que reemplazaras la declaración if con lo siguiente:if not dirnames and not filenames:
__bool__
función no está definida en la secuencia subyacente.