valores usar true relacionales operadores operaciones not logicas false ejemplos declarar como booleanos bool python if-statement boolean

usar - Asignación elegante de Python basada en valores True/False



true y false en python (11)

¿Qué hay de usar un dict?

name = {(True, True, True): "first", (True, True, False): "second", (True, False, True): "third", (True, False, False): "fourth", (False, True, True): "fifth", (False, True, False): "sixth", (False, False, True): "seventh", (False, False, False): "eighth"} print name[a,b,c] # prints "fifth" if a==False, b==True, c==True etc.

Tengo una variable que quiero establecer dependiendo de los valores en tres booleanos. La forma más directa es una instrucción if seguida de una serie de elifs:

if a and b and c: name = ''first'' elif a and b and not c: name = ''second'' elif a and not b and c: name = ''third'' elif a and not b and not c: name = ''fourth'' elif not a and b and c: name = ''fifth'' elif not a and b and not c: name = ''sixth'' elif not a and not b and c: name = ''seventh'' elif not a and not b and not c: name = ''eighth''

Esto es un poco incómodo, y me pregunto si hay una forma más pitonica para manejar este problema. Un par de ideas vienen a la mente.

  1. Diccionario de pirateo:

    name = {a and b and c: ''first'', a and b and not c: ''second'', a and not b and c: ''third'', a and not b and not c: ''fourth'', not a and b and c: ''fifth'', not a and b and not c: ''sixth'', not a and not b and c: ''seventh'', not a and not b and not c: ''eighth''}[True]

Lo llamo hack porque no soy demasiado salvaje porque siete de las claves son falsas y se anulan entre sí.

  1. Y / o magia

    name = (a and b and c and ''first'' or a and b and not c and ''second'' or a and not b and c and ''third'' or a and not b and not c and ''fourth'' or not a and b and c and ''fifth'' or not a and b and not c and ''sixth'' or not a and not b and c and ''seventh'' or not a and not b and not c and ''eighth'')

Esto funciona porque Python, ands y ors devuelven el último valor para ser evaluado, pero debes saberlo para poder entender este extraño código.

Ninguna de estas tres opciones es muy satisfactoria. ¿Que recomiendas?


¿Qué pasa con los if anidados? Esto significa que no tiene que verificar todo varias veces y leer más claramente para mí (aunque quizás no sea tan inteligente como algunas de las otras respuestas):

if a: if b: if c: name="first" else: name="second" else: if c: name="third" else: name="fourth" else: if b: if c: name="fifth" else: name="sixth" else: if c: name="seventh" else: name="eighth"


Aquí hay un enfoque de tabla de verdad:

lookup = {''000'': ''eighth'', ''001'': ''seventh'', ''010'': ''sixth'', ''011'': ''fifth'', ''100'': ''fourth'', ''101'': ''third'', ''110'': ''second'', ''111'': ''first''} def key(a, b, c): return ''''.join([str(a),str(b),str(c)]) name = lookup[key(0,1,1)]


Como obtiene todas las combinaciones, puede crear un índice basado en los valores como este:

def value(a,b,c ): values = [''8th'',''7th'',''6th'',''5th'',''4th'',''3rd'',''2nd'',''1st''] index = ( 4 if a else 0 ) + ( 2 if b else 0 ) + ( 1 if c else 0 ) return values[index] if __name__ == "__main__": print value(True, True, True ) print value(True, True, False ) print value(True, False, True ) print value(True, False, False ) print value(False, True, True ) print value(False, True, False) print value(False, False, True ) print value(False, False, False)

salida:

1st 2nd 3rd 4th 5th 6th 7th 8th


Me gustaría ir a la solución de listas / bits de @OscarRyz, @Clint y @Sven, pero aquí hay otra:

S1 = frozenset([''first'', ''second'', ''third'', ''fourth'']) S2 = frozenset([''first'', ''second'', ''fifth'', ''sixth'']) S3 = frozenset([''first'', ''third'', ''fifth'', ''seventh'']) last = ''eighth'' empty = frozenset([])

def value(a, b, c): for r in (a and S1 or empty) & (b and S2 or empty) & (c and S3 or empty): return r return last


Otra opción sería crear una función auxiliar:

def first_true(*args): true_vals = (arg for arg in args if arg[0]) return next(true_vals)[1] name = first_true((a and b and c, ''first''), (a and b and not c, ''second''), (a and not b and c, ''third''), (a and not b and not c, ''fourth''), (not a and b and c, ''fifth''), (not a and b and not c, ''sixth''), (not a and not b and c, ''seventh''), (not a and not b and not c, ''eighth''))

Este método supone que una de las pruebas pasadas será verdadera. También podría hacerse más perezoso con lambdas.


Para medir velocidades:

from time import clock a,b,c = True,False,False A,B,C,D,E,F,G,H = [],[],[],[],[],[],[],[] for j in xrange(30): te = clock() for i in xrange(10000): name = (a and b and c and ''first'' or a and b and not c and ''second'' or a and not b and c and ''third'' or a and not b and not c and ''fourth'' or not a and b and c and ''fifth'' or not a and b and not c and ''sixth'' or not a and not b and c and ''seventh'' or not a and not b and not c and ''eighth'') A.append(clock()-te) te = clock() for i in xrange(10000): if a and b and c: name = ''first'' elif a and b and not c: name = ''second'' elif a and not b and c: name = ''third'' elif a and not b and not c: name = ''fourth'' elif not a and b and c: name = ''fifth'' elif not a and b and not c: name = ''sixth'' elif not a and not b and c: name = ''seventh'' elif not a and not b and not c: name = ''eighth'' B.append(clock()-te) #===================================================================================== li = [''eighth'', ''seventh'', ''sixth'', ''fifth'', ''fourth'', ''third'', ''second'', ''first''] te = clock() for i in xrange(10000): name = li[a*4 + b*2 + c] C.append(clock()-te) #===================================================================================== nth = [''eighth'', ''seventh'', ''sixth'', ''fifth'', ''fourth'', ''third'', ''second'', ''first''] te = clock() for i in xrange(10000): name = nth[(a and 4 or 0) | (b and 2 or 0) | (c and 1 or 0)] D.append(clock()-te) nth = [''eighth'', ''seventh'', ''sixth'', ''fifth'', ''fourth'', ''third'', ''second'', ''first''] te = clock() for i in xrange(10000): name = nth[(a and 4 or 0) + (b and 2 or 0) + (c and 1 or 0)] E.append(clock()-te) #===================================================================================== values = [''eighth'', ''seventh'', ''sixth'', ''fifth'', ''fourth'', ''third'', ''second'', ''first''] te = clock() for i in xrange(10000): name = values[( 4 if a else 0 )| ( 2 if b else 0 ) | ( 1 if c else 0 )] F.append(clock()-te) values = [''eighth'', ''seventh'', ''sixth'', ''fifth'', ''fourth'', ''third'', ''second'', ''first''] te = clock() for i in xrange(10000): name = values[( 4 if a else 0 ) + ( 2 if b else 0 ) + ( 1 if c else 0 )] G.append(clock()-te) #===================================================================================== dic = {(True, True, True): "first", (True, True, False): "second", (True, False, True): "third", (True, False, False): "fourth", (False, True, True): "fifth", (False, True, False): "sixth", (False, False, True): "seventh", (False, False, False): "eighth"} te = clock() for i in xrange(10000): name = dic[a,b,c] H.append(clock()-te) print min(A),''/n'', min(B),''/n/n'', min(C),''/n/n'', min(D),''/n'',min(E),''/n/n'',min(F),''/n'', min(G),''/n/n'', min(H)

Resultado

0.0480533140385 0.0450973517584 0.0309056039245 0.0295291720037 0.0286550385594 0.0280122194301 0.0266760160858 0.0249769174574


Puedes pensar que a, byc son tres bits que, al juntarse, forman un número entre 0 y 7. Luego, puedes tener una matriz de los valores [''primero'', ''segundo'', ... ''octavo'' ] y usa el valor del bit como un desplazamiento en la matriz. Esto sería simplemente dos líneas de código (una para ensamblar los bits en un valor de 0-7 y otra para buscar el valor en la matriz).

Aquí está el código:

nth = [''eighth'', ''seventh'', ''sixth'', ''fifth'', ''fourth'', ''third'', ''second'', ''first''] nth[(a and 4 or 0) | (b and 2 or 0) | (c and 1 or 0)]


Tal vez no mucho mejor, pero ¿qué tal

results = [''first'', ''second'', ''third'', ''fourth'', ''fifth'', ''sixth'', ''seventh'', ''eighth''] name = results[((not a) << 2) + ((not b) << 1) + (not c)]


si a, b, c son realmente booleanos:

li = [''eighth'', ''seventh'', ''sixth'', ''fifth'', ''fourth'', ''third'', ''second'', ''first''] name = li[a*4 + b*2 + c]

si no son booleanos:

li = [''eighth'', ''seventh'', ''sixth'', ''fifth'', ''fourth'', ''third'', ''second'', ''first''] a,b,c = map(bool,(a,b,c)) name = li[a*4 + b*2 + c]

idea de Clint Miller


si su objetivo es evitar escribir muchos "ands" y expresiones booleanas, puede usar el número primo y solo una condición como esta (ejemplo para 2 condiciones)

cond = (2**cond_1)*(3**cond_2)

asi que

cond == 1 #means cond_1 and cond_2 are False cond == 2 #means cond_1 is True and con_2 is False cond == 3 #means cond_1 is False and con_2 is True cond == 6 #means con_1 and Con_2 are True

Este truco se puede usar para 3 condiciones usando 3 primos, etc.

Me gusta esto...

cond = (2**a)*(3**b)*(5**c) name = {30:''first'', 6: ''second'', 10:''third'', 2:''fourth'', 15:''fifth'', 3:''sixth'', 5:''seventh'', 1:''eighth''}[cond]