versiones guia español descargar actualizar python idioms

guia - ¿Por qué verificar implícitamente el vacío en Python?



qgis manual (8)

"Lo simple es mejor que lo complejo".

"La legibilidad cuenta".

Tomemos, por ejemplo, if users : es más legible que if len(users) == 0

El Zen de Python dice que explícito es mejor que implícito.

Sin embargo, la manera Pythonic de verificar una colección c para el vacío es:

if not c: # ...

y verificar si una colección no está vacía se hace como:

if c: # ...

ídem para cualquier cosa que pueda tener "zeroness" o "vacío" (tuplas, enteros, cadenas, ninguno, etc.)

¿Cuál es el propósito de esto? ¿Mi código será más defectuoso si no hago esto? ¿O permite más casos de uso (es decir, algún tipo de polimorfismo) ya que las personas pueden anular estas coerciones booleanas?


El polimorfismo booleano implícito es parte de muchos idiomas. De hecho, el idioma

if msg: print str(len(msg)) + '' char message: '' + msg

Podría decirse que viene de c!

void print_msg(char * msg) { if (msg) { printf("%d char message: %s", (int) strlen(msg), msg); } }

Un puntero no asignado debe contener NULL , que convenientemente se evalúa como falso, lo que nos permite evitar un error de segmentación.

Este es un concepto tan fundamental que dificultaría que Python lo rechazara. De hecho, dada la versión bastante torpe del polimorfismo booleano disponible en c, inmediatamente queda claro (al menos para mí) que Python ha hecho este comportamiento mucho más explícito al permitir que cualquier tipo tenga una conversión booleana personalizable y bien definida a través de __nonzero__ .


Esta mejor práctica no es sin razón.

Al probar if object: básicamente está llamando al método __nonzero__ los objetos, que se puede anular e implementar de acuerdo con el comportamiento del objeto.

Por ejemplo, el método __nonzero__ en las colecciones devolverá un valor booleano basado en si la colección está vacía o no.

(Referencia: http://docs.python.org/reference/datamodel.html )


Las listas vacías que se evalúan como falsas y las listas no vacías que se evalúan como verdaderas es una convención central de Python que es lo suficientemente explícita. Si el contexto de la sentencia if incluso comunica el hecho de que c es una lista, len(c) == 0 no sería mucho más explícito.

Creo que len(c) == 0 solo es más explícito si realmente desea verificar la longitud y no el zeroness mágico o el vacío porque su evaluación puede diferir de la verificación de la longitud.


Otros ya han notado que esta es una extensión lógica de la tradición (al menos tan pronto como C, quizás antes) que cero es falso en un contexto booleano, y que no es cero es verdadero. Otros también han notado que en Python puedes lograr algunos efectos especiales con métodos mágicos personalizados y otros. (Y esto responde directamente a su pregunta "¿habilita más casos de uso?") Otros ya han señalado que los programadores experimentados de Python habrán aprendido esta convención y estarán acostumbrados a la convención, por lo que es perfectamente obvio y explícito para ellos.

Pero honestamente, si no te gusta esa convención, y solo estás programando para tu propio disfrute y beneficio, simplemente no lo sigas . Es mucho, mucho mejor ser explícito, claro y redundante de lo que se debe ofuscar, y casi siempre es mejor equivocarse del lado de la redundancia que de la ofuscación.

Dicho esto, cuando se trata de eso, no es una convención difícil de aprender, y si está programando como parte de un proyecto grupal, es mejor seguir las convenciones del proyecto, incluso si no está de acuerdo con ellos.


Posiblemente triunfado por el primer y tercer elemento:

  • Lo bello es mejor que lo feo.
  • Lo simple es mejor que lo complejo.

Si lo prefiere, puede escribir if len(lst) > 0 , pero ¿cuál sería el punto? Python usa algunas convenciones, una de ellas es que los contenedores vacíos se consideran falsos.

Puede personalizar esto con el object.__nonzero__(self) :

Llamado para implementar pruebas de valor real y la operación integrada bool (); debe devolver False o True, o sus equivalentes enteros 0 o 1. Cuando este método no está definido, se __len__() , si está definido, y el objeto se considera verdadero si su resultado es distinto de cero. Si una clase no define __len__() ni __nonzero__() , todas sus instancias se consideran verdaderas.


if c: # ...

es explícito El "if" indica explícitamente que la siguiente expresión se evaluará en un contexto booleano.

Es justo argumentar que

if c == 0: # ...

Es más claro, y un novato en programación podría estar de acuerdo.

Pero para un programador experimentado (al menos éste) este último no es más claro, es redundante. Ya sé que c se comparará con 0 debido al "si"; No necesito que me lo digan dos veces.