2010-07-04 8 views
59

False es equivalente a 0 y True es equivalente 1 por lo que es posible hacer algo como esto:¿Es pitónico usar bools como ints?

def bool_to_str(value): 
    """value should be a bool""" 
    return ['No', 'Yes'][value] 

bool_to_str(True) 

Aviso cómo el valor es bool pero se utiliza como un int.

¿Es este tipo de uso Pythonic o debería evitarse?

+1

Esto es esencialmente un duplicado de http://stackoverflow.com/questions/2764017/is-false-0-and-true-1-in-python-an-implementation-detail-or-is- it-guarantee, ¡cuyas respuestas también son una lectura interesante! – EOL

Respuesta

154

Voy a ser la voz extraña (ya que todas las respuestas están denunciando el uso del hecho de que False == 0 y True == 1, como garantiza el idioma) ya que afirmo que el uso de este hecho para simplificar su código está perfectamente bien.

Históricamente, las operaciones lógicas verdadero/falso tendían a simplemente usar 0 para falso y 1 para verdadero; En el transcurso del ciclo de vida de Python 2.2, Guido notó que muchos módulos comenzaron con asignaciones como false = 0; true = 1 y esto produjo un repetitivo y una variación inútil (esto último porque la capitalización de verdadero y falso estaba por todos lados, algunos usaban mayúsculas, algunas minúsculas, algunas mayúsculas iniciales) y así introdujo la subclase bool de int y sus True y False constantes.

Había algún retroceso en el momento, ya que muchos de nosotros el temor de que el nuevo tipo y constantes serían utilizados por los principiantes de Python a restringir las habilidades del lenguaje, pero Guido fue firme en que estábamos a ser pesimista: nadie lo haría Alguna vez entendió Python tan mal, por ejemplo, como para evitar el uso perfectamente natural de False y True como índices de lista, o en una sumatoria, u otras expresiones perfectamente claras y útiles.

Las respuestas a este hilo demostrar que teníamos razón: como temíamos, una total falta de comprensión de los papeles de este tipo y las constantes ha surgido, y las personas son evitar, y, peor aún !, instando a otros a evitar , construcciones Python perfectamente naturales a favor de giros inútiles.

lucha contra la corriente de tales malentendidos, insto a todos a utilizar Python Python como, no tratar de forzarlo en el molde de otras lenguas cuya funcionalidad y estilo preferido son bastante diferentes. En Python , verdadero y falso son el 99,9% como 1 y 0, que se diferencian exclusivamente en su forma str(...) (y por lo tanto repr(...)) - para todos los demás operación, excepto stringification, apenas siente libre al utilizarlos sin contorsiones. Eso va para la indexación, la aritmética, operaciones de bits, etc, etc, etc.

+8

+1 Contraste con Ruby, que fuerza 'val? 1: 0' y basura gimnástica similar si necesita tratar un bool como un int. –

+18

"nadie entendería Python tan mal, por ejemplo, como para evitar el uso perfectamente natural de False y True como índices de lista". Ciertamente no me opongo a usarlos de esa manera, pero de ninguna manera creo que sea "natural" que la gente indexe en una lista con un tipo booleano, a menos que conozcan las subclases 'bool'' int' –

+3

Interesante historia ¡lección en verdad! Sin embargo, yo diría que hay algo que dice que la mayoría de las personas distingue entre booleanos y enteros (yo sí ...). En cierto modo, las personas están definiendo lo que significa "usar Python como Python": la mayoría de nosotros siente que hay una distinción lógica entre los dos tipos (las matemáticas también lo hacen en su mayoría: la lógica no necesita aritmética). Estoy bastante contento con el hecho de que Python nos permite pensar de esta manera. – EOL

35

duda:

def bool_to_str(value): 
    "value should be a bool" 
    return 'Yes' if value else 'No' 

es más fácil de leer.

+2

Discutiría con ese ...sí, usar la cosita 'x if foo else y' es más pitonica, pero sigo creyendo que solo se ve feo y a menudo aumenta el código. Creo que el código de la pregunta ** parece ** más claro, puede ser confuso para las personas que no conocen la conversión implícita de bool a int, pero 'x if foo else y' es tan confuso para alguien que proviene de el 'foo? x: y' mundo de las cosas. Aunque debo admitir que para las personas que están aprendiendo su primer idioma, el 'x if foo else y' puede ser el más claro. –

+2

@ Ivo, +1 como estoy de acuerdo con la sustancia, pero no estoy de acuerdo con que la construcción "ternaria" (con la condición en el medio, no al principio como en C) sea particularmente natural o clara para los novatos (es la menos importante males en muchos casos, eso es algo diferente ;-). –

+0

no estoy seguro, parece que también tengo uno, más o menos al mismo tiempo (¡y también sin comentarios!). –

5

En realidad, es una característica del lenguaje que Falso == 0 == 1 y Verdadero (que no depende de la aplicación): Is False == 0 and True == 1 in Python an implementation detail or is it guaranteed by the language?

Sin embargo, estoy de acuerdo con la mayoría de las otras respuestas: no son formas más legibles de obtener el mismo resultado que ['No', 'Yes'][value], mediante el uso del … if value else … o de un diccionario, que tienen las ventajas respectivas de insinuar y afirmar que value es un booleano.

Además, el … if value else … sigue la convención usual de que no 0 es verdadero: también funciona incluso cuando value == -2 (valor es verdadero), como lo insinúa dalia. Los enfoques de listas y dict no son tan sólidos, en este caso, así que no los recomendaría.

+0

¿Por qué el voto a favor? – EOL

13

Su código parece inexacta en algunos casos:

>>> def bool_to_str(value): 
...  """value should be a bool""" 
...  return ['No', 'Yes'][value] 
... 
>>> bool_to_str(-2) 
'No' 

y recomiendo que utilice sólo el operador condicional para facilitar la lectura:

def bool_to_str(value): 
    """value should be a bool""" 
    return "Yes" if value else "No" 
+14

El nombre de la función es 'bool_to_str', con el comentario de doc' value debe ser un bool', y te sorprende que da una respuesta incorrecta cuando lo pasas '-2' :) –

+0

Por otro lado, yo discutiría que es habitual suponer que no-0 significa verdadero ... Lo que muestra el ejemplo de Dalia es que el método '... if ... else ...' le permite producir código que no es innecesariamente restrictivo. – EOL

+3

+1 Aunque estoy de acuerdo con la respuesta de Alex Martelli en general, en este caso parece "más Pythonic" aprovechar la conversión implícita a 'bool' que ofrece' ... if ... else ... '. Entonces la función funciona para bools y cualquier otra cosa. Aunque quizás no sea el mejor ejemplo, ya que no estoy en desacuerdo con la idea de usar bools como ints. – shambulator

1

Usar un bool como int es bastante correcto porque bool es la subclase de int.

>>> isinstance(True, int) 
True 
>>> isinstance(False, int) 
True 

Sobre su código: Poniéndolo en una función de una línea así, está por encima. Los lectores necesitan encontrar su fuente de función o documentos y leerlo (el nombre de la función no le dice mucho). Esto interrumpe el flujo. Simplemente póngalo en línea y no use una lista (construida en tiempo de ejecución), use una tupla (construida en tiempo de compilación si los valores son constantes). Ejemplo:

print foo, bar, num_things, ("OK", "Too many!)[num_things > max_things] 
130

Estoy con Alex. False==0 y True==1, y no hay nada de malo en eso.

Sin embargo, en Python 2.5 y más tarde me gustaría escribir la respuesta a esta pregunta en particular el uso de la expresión condicional de Python:

def bool_to_str(value): 
    return 'Yes' if value else 'No' 

De esa manera no hay necesidad de que el argumento es en realidad un bool - al igual que if x: ... acepta cualquier tipo para x, la función bool_to_str() debe hacer lo correcto cuando se pasa Ninguno, una cadena, una lista o 3.14.

0

Personalmente creo que depende de cómo usted desea utilizar este hecho, aquí hay dos ejemplos

  1. Simplemente basta con utilizar booleano como sentencia condicional está muy bien. La gente hace esto todo el tiempo.

    a = 0 
    if a: 
        do something 
    
  2. Sin embargo dicen que desea contar el número de elementos se realiza correctamente, el código tal vez no muy agradable que otras personas puedan leer.

    def succeed(val): 
        if do_something(val): 
         return True 
        else: 
         return False 
    
    count = 0 
    values = [some values to process] 
    for val in values: 
        count += succeed(val) 
    

Pero veo la mirada código de producción como esta.

all_successful = all([succeed(val) for val in values]) 
at_least_one_successful = any([succeed(val) for val in values]) 
total_number_of_successful = sum([succeed(val) for val in values])