sumar - variable tipo texto en python
¿Cómo se obtiene el xor lógico de dos variables en Python? (18)
¿Qué tal esto?
(not b and a) or (not a and b)
dará a
si b
es falso
dará b
si a
es falso
dará False
contrario
O con la expresión ternaria de Python 2.5+:
(False if a else b) if b else a
¿Cómo se obtiene el xor lógico de dos variables en Python?
Por ejemplo, tengo dos variables que espero sean cadenas. Quiero probar que solo uno de ellos contiene un valor True (no es None o la cadena vacía):
str1 = raw_input("Enter string one:")
str2 = raw_input("Enter string two:")
if logical_xor(str1, str2):
print "ok"
else:
print "bad"
El operador ^
parece ser bit a bit y no está definido en todos los objetos:
>>> 1 ^ 1
0
>>> 2 ^ 1
3
>>> "abc" ^ ""
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for ^: ''str'' and ''str''
A veces me encuentro trabajando con 1 y 0 en lugar de valores booleanos de verdadero y falso. En este caso xor puede definirse como
z = (x + y) % 2
que tiene la siguiente tabla de verdad:
x
|0|1|
-+-+-+
0|0|1|
y -+-+-+
1|1|0|
-+-+-+
Algunas de las implementaciones sugeridas aquí causarán una evaluación repetida de los operandos en algunos casos, lo que puede llevar a efectos secundarios no deseados y, por lo tanto, debe evitarse.
Dicho esto, una implementación xor
que devuelva True
o False
es bastante simple; El que devuelve uno de los operandos, si es posible, es mucho más complicado, porque no existe un consenso sobre qué operando debe ser el elegido, especialmente cuando hay más de dos operandos. Por ejemplo, ¿debería xor(None, -1, [], True)
devolver None
, []
o False
? Apuesto a que cada respuesta aparece para algunas personas como la más intuitiva.
Ya sea para el resultado Verdadero o Falso, hay tantas como cinco opciones posibles: devolver el primer operando (si coincide con el resultado final en el valor, si no es booleano), devolver la primera coincidencia (si existe al menos uno, si no es el booleano), devuelve el último operando (si ... más ...), devuelve la última coincidencia (si ... más ...), o siempre devuelve booleano. En total, eso es 5 ** 2 = 25 sabores de xor
.
def xor(*operands, falsechoice = -2, truechoice = -2):
"""A single-evaluation, multi-operand, full-choice xor implementation
falsechoice, truechoice: 0 = always bool, +/-1 = first/last operand, +/-2 = first/last match"""
if not operands:
raise TypeError(''at least one operand expected'')
choices = [falsechoice, truechoice]
matches = {}
result = False
first = True
value = choice = None
# avoid using index or slice since operands may be an infinite iterator
for operand in operands:
# evaluate each operand once only so as to avoid unintended side effects
value = bool(operand)
# the actual xor operation
result ^= value
# choice for the current operand, which may or may not match end result
choice = choices[value]
# if choice is last match;
# or last operand and the current operand, in case it is last, matches result;
# or first operand and the current operand is indeed first;
# or first match and there hasn''t been a match so far
if choice < -1 or (choice == -1 and value == result) or (choice == 1 and first) or (choice > 1 and value not in matches):
# store the current operand
matches[value] = operand
# next operand will no longer be first
first = False
# if choice for result is last operand, but they mismatch
if (choices[result] == -1) and (result != value):
return result
else:
# return the stored matching operand, if existing, else result as bool
return matches.get(result, result)
testcases = [
(-1, None, True, {None: None}, [], ''a''),
(None, -1, {None: None}, ''a'', []),
(None, -1, True, {None: None}, ''a'', []),
(-1, None, {None: None}, [], ''a'')]
choices = {-2: ''last match'', -1: ''last operand'', 0: ''always bool'', 1: ''first operand'', 2: ''first match''}
for c in testcases:
print(c)
for f in sorted(choices.keys()):
for t in sorted(choices.keys()):
x = xor(*c, falsechoice = f, truechoice = t)
print(''f: %d (%s)/tt: %d (%s)/tx: %s'' % (f, choices[f], t, choices[t], x))
print()
Como explicó Zach , puedes usar:
xor = bool(a) ^ bool(b)
Personalmente, prefiero un dialecto ligeramente diferente:
xor = bool(a) + bool(b) == 1
Este dialecto está inspirado en un lenguaje de diagramación lógica que aprendí en la escuela donde "OR" se denota por un cuadro que contiene ≥1
(mayor o igual a 1) y "XOR" se denota por un cuadro que contiene =1
.
Esto tiene la ventaja de implementar correctamente exclusivos o en múltiples operandos.
- "1 = a ^ b ^ c ..." significa que el número de operandos verdaderos es impar. Este operador es "paridad".
- "1 = a + b + c ..." significa que exactamente un operando es verdadero. Esto es "exclusivo o", que significa "uno a la exclusión de los otros".
Como no veo la variante simple de xor usando argumentos variables y solo operación en los valores de Verdadero Verdadero o Falso, simplemente lo lanzaré aquí para que cualquiera lo use. Es como lo han señalado otros, bonito (por no decir muy) sencillo.
def xor(*vars):
sum = bool(False)
for v in vars:
sum = sum ^ bool(v)
return sum
Y el uso también es sencillo:
if xor(False, False, True, False):
print "Hello World!"
Como este es el XOR lógico n-ario generalizado, su valor de verdad será Verdadero siempre que el número de operandos Verdaderos sea impar (y no solo cuando uno sea Verdadero, este es solo un caso en el que XOR n-aria es Verdadero).
Por lo tanto, si está buscando un predicado n-ario que solo sea Verdadero cuando exista uno de sus operandos, es posible que desee utilizar:
def isOne(*vars):
sum = bool(False)
for v in vars:
if sum and v:
return False
else:
sum = sum or v
return sum
Es fácil cuando sabes lo que hace XOR:
def logical_xor(a, b):
return (a and not b) or (not a and b)
test_data = [
[False, False],
[False, True],
[True, False],
[True, True],
]
for a, b in test_data:
print ''%r xor %s = %r'' % (a, b, logical_xor(a, b))
Esto obtiene el XOR exclusivo lógico para dos (o más) variables
str1 = raw_input("Enter string one:")
str2 = raw_input("Enter string two:")
any([str1, str2]) and not all([str1, str2])
El primer problema con esta configuración es que lo más probable es que atraviese la lista completa dos veces y, como mínimo, verificará al menos uno de los elementos dos veces. Por lo tanto, puede aumentar la comprensión del código, pero no se presta a la velocidad (que puede diferir de manera despreciable en función de su caso de uso).
El segundo problema con esta configuración es que comprueba la exclusividad independientemente del número de variables. Al principio, esto se puede considerar como una característica, pero el primer problema se vuelve mucho más significativo a medida que aumenta el número de variables (si es que alguna vez lo hacen).
Exclusivo O se define como sigue
def xor( a, b ):
return (a or b) and not (a and b)
Exclusivo o ya está integrado en Python, en el módulo del operator
:
from operator import xor
xor(bool(a), bool(b))
He probado varios enfoques y not a != (not b)
parece ser el más rápido.
Aquí hay algunas pruebas
%timeit not a != (not b)
10000000 loops, best of 3: 78.5 ns per loop
In [130]: %timeit bool(a) != bool(b)
1000000 loops, best of 3: 343 ns per loop
In [131]: %timeit not a ^ (not b)
10000000 loops, best of 3: 131 ns per loop
Hilo gratificante:
Idea anodidora ... Solo intente (puede ser) la expresión pitónica «no es» para obtener el comportamiento del «xor» lógico
La tabla de verdad sería:
>>> True is not True
False
>>> True is not False
True
>>> False is not True
True
>>> False is not False
False
>>>
Y para su cadena de ejemplo:
>>> "abc" is not ""
True
>>> ''abc'' is not ''abc''
False
>>> ''abc'' is not ''''
True
>>> '''' is not ''abc''
True
>>> '''' is not ''''
False
>>>
Sin embargo; como se indicó anteriormente, depende del comportamiento real que desee extraer sobre cualquier par de cuerdas, ya que las cuerdas no son boleanas ... y aún más: si «Bucea en Python» encontrará «La naturaleza peculiar de" y "y" o "» http://www.diveintopython.net/power_of_introspection/and_or.html
Perdón por mi inglés escrito, no es mi lengua natal.
Saludos.
Podemos encontrar fácilmente xor de dos variables mediante el uso de:
def xor(a,b):
return a !=b
Ejemplo:
xor (Verdadero, Falso) >>> Verdadero
Sé que esto es tarde, pero tuve un pensamiento y podría valer la pena, solo por documentación. Quizás esto funcione: np.abs(xy)
La idea es que
- si x = Verdadero = 1 e y = Falso = 0, entonces el resultado sería | 1-0 | = 1 = Verdadero
- si x = Falso = 0 y y = Falso = 0, entonces el resultado sería | 0-0 | = 0 = Falso
- si x = True = 1 y y = True = 1 entonces el resultado sería | 1-1 | = 0 = Falso
- si x = False = 0 y y = True = 1 entonces el resultado sería | 0-1 | = 1 = True
Si ya está normalizando las entradas a booleanos, entonces! = Es xor.
bool(a) != bool(b)
Siempre puede usar la definición de xor para calcularla a partir de otras operaciones lógicas:
(a and not b) or (not a and b)
Pero esto es un poco demasiado detallado para mí, y no es particularmente claro a primera vista. Otra forma de hacerlo es:
bool(a) ^ bool(b)
El operador xor en dos booleanos es xor lógico (a diferencia de los ints, donde es bitwise). Lo que tiene sentido, ya que bool
es solo una subclase de int
, pero se implementa para tener solo los valores 0
y 1
. Y xor lógico es equivalente a xor a nivel de bit cuando el dominio está restringido a 0
y 1
.
Así que la función logical_xor
se implementaría como:
def logical_xor(str1, str2):
return bool(str1) ^ bool(str2)
Crédito a Nick Coghlan en la lista de correo Python-3000 .
Simple, fácil de entender:
sum( (bool(a), bool(b) ) == 1
Si lo que busca es una opción exclusiva, puede expandirse a múltiples argumentos:
sum( bool(x) for x in y ) == 1
XOR se implementa en operator.xor
.
- Python lógico
or
:A or B
: devuelveA
sibool(A)
esTrue
, de lo contrario devuelveB
- Python lógico
and
:A and B
: devuelveA
sibool(A)
esFalse
, de lo contrario devuelveB
Para mantener la mayor parte de esa forma de pensar, mi definición lógica o lógica sería:
def logical_xor(a, b):
if bool(a) == bool(b):
return False
else:
return a or b
De esa manera puede devolver a
, b
, o False
:
>>> logical_xor(''this'', ''that'')
False
>>> logical_xor('''', '''')
False
>>> logical_xor(''this'', '''')
''this''
>>> logical_xor('''', ''that'')
''that''