Tengo un script de Python que puede recibir cero o tres argumentos de línea de comando. (Se ejecuta con el comportamiento predeterminado o necesita los tres valores especificados).
¿Cuál es la sintaxis ideal para algo como:
if a and (not b or not c) or b and (not a or not c) or c and (not b or not a):
?
python
if-statement
Chris Wilson
fuente
fuente
len(sys.argv)
siempre será al menos 1: incluye el ejecutable comoargv[0]
.if not (a and b and c)
(cero argumentos) y luegoif a and b and c
(los tres argumentos)?Respuestas:
Si te refieres a una forma mínima, ve con esto:
Lo que traduce el título de su pregunta.
ACTUALIZACIÓN: como dicen correctamente Volatility y Supr, puede aplicar la ley de De Morgan y obtener un equivalente:
Mi consejo es usar el formulario que sea más significativo para usted y para otros programadores. El primero significa "hay algo falso, pero también algo verdadero" , el segundo "hay algo verdadero, pero no todo" . Si tuviera que optimizar o hacer esto en hardware, elegiría el segundo, aquí solo elegir el más legible (también teniendo en cuenta las condiciones que probará y sus nombres). Elegí el primero.
fuente
if not (a and b and c) and (a or b or c)
if (a or b or c) and not (a and b and c)
para que coincida perfectamente con el título;)if any([a,b,c]) and not all([a,b,c])
Qué tal si:
Otra variante:
fuente
sum(conditions)
puede salir mal si alguno de ellos vuelve,2
por ejemplo, que esTrue
.sum(map(bool, conditions))
Esta pregunta ya tenía muchas respuestas altamente votadas y una respuesta aceptada, pero todas hasta ahora estaban distraídas por varias formas de expresar el problema booleano y perdieron un punto crucial:
Esta lógica no debe ser responsabilidad de su código en primer lugar , sino que debe ser manejada por el
argparse
módulo. No se moleste en escribir una declaración if compleja, en su lugar, prefiera configurar su analizador de argumentos de la siguiente manera:Y sí, debería ser una opción, no un argumento posicional, porque después de todo es opcional .
editado: para abordar la preocupación de LarsH en los comentarios, a continuación se muestra un ejemplo de cómo podría escribirlo si estaba seguro de que deseaba la interfaz con 3 o 0argumentos posicionales . Soy de la opinión de que la interfaz anterior es mejor estilo, porque losargumentos opcionales deberían ser opciones , pero aquí hay un enfoque alternativo en aras de la integridad. Tenga en cuenta la omisión de kwarg
usage
al crear su analizador, porque deargparse
lo contrario generará automáticamente un mensaje de uso engañoso.Aquí hay algunos ejemplos de uso:
fuente
Yo iría por:
Creo que esto debería cortocircuitar de manera bastante eficiente
Explicación
Al hacer
conds
un iterador, el primer uso deany
hará un cortocircuito y dejará el iterador apuntando al siguiente elemento si algún elemento es verdadero; de lo contrario, consumirá toda la lista y seráFalse
. El siguienteany
toma los elementos restantes en el iterable, y se asegura de que no haya otros valores verdaderos ... Si los hay, toda la declaración no puede ser verdadera, por lo tanto no hay un elemento único (por lo tanto, cortocircuitos de nuevo). El últimoany
regresaráFalse
o agotará el iterable y seráTrue
.nota: lo anterior verifica si solo se establece una condición
Si desea verificar si uno o más elementos, pero no todos los elementos están configurados, puede usar:
fuente
[a, b, c] = [True, True, False]
¿No debería su código "imprime"False
, mientras que la salida esperada esTrue
?iter
.any
yall
va a consumir perezosamente la lista, es cierto, ¡pero la lista ya estaba completamente evaluada cuando llegas allí!La oración en inglés:
Se traduce a esta lógica:
La palabra "pero" generalmente implica una conjunción, en otras palabras, "y". Además, "todos ellos" se traduce en una conjunción de condiciones: esta condición, y esa condición, y otra condición. El "no" invierte toda esa conjunción.
No estoy de acuerdo con la respuesta aceptada. El autor descuidó aplicar la interpretación más directa a la especificación y descuidó aplicar la Ley de De Morgan para simplificar la expresión a menos operadores:
mientras afirma que la respuesta es una "forma mínima".
fuente
Esto regresa
True
si una y solo una de las tres condiciones esTrue
. Probablemente lo que quería en su código de ejemplo.fuente
¿Qué pasa con: (condición única)
Tenga en cuenta que si permite dos condiciones también podría hacerlo
fuente
1 <= bool(a) + bool(b) + bool(c) <= 2
.Para ser claros, ¿desea tomar su decisión en función de la cantidad de parámetros que son VERDADEROS lógicos (en caso de argumentos de cadena, no vacíos)?
Entonces tomaste una decisión:
Ahora la lógica es más clara.
fuente
¿Y por qué no solo contarlos?
fuente
Si no le importa ser un poco críptico, puede rodar de manera simple con
0 < (a + b + c) < 3
lo que regresarátrue
si tiene entre una y dos declaraciones verdaderas y falso si todas son falsas o ninguna es falsa.Esto también se simplifica si usa funciones para evaluar los bools, ya que solo evalúa las variables una vez y eso significa que puede escribir las funciones en línea y no necesita almacenar temporalmente las variables. (Ejemplo:.
0 < ( a(x) + b(x) + c(x) ) < 3
)fuente
La pregunta indica que necesita los tres argumentos (a y byc) o ninguno de ellos (no (a o b o c))
Esto da:
(a y byc) o no (a o b o c)
fuente
Según tengo entendido, tiene una función que recibe 3 argumentos, pero si no lo hace, se ejecutará con el comportamiento predeterminado. Como no ha explicado lo que debería suceder cuando se proporcionan 1 o 2 argumentos, asumiré que simplemente debería hacer el comportamiento predeterminado. En cuyo caso, creo que encontrará la siguiente respuesta muy ventajosa:
Sin embargo, si desea que 1 o 2 argumentos se manejen de manera diferente:
nota: Esto supone que "
False
" los valores no se pasarán a este método.fuente
Si trabaja con un iterador de condiciones, el acceso puede ser lento. Pero no necesita acceder a cada elemento más de una vez, y no siempre necesita leerlo todo. Aquí hay una solución que funcionará con generadores infinitos:
fuente
Cuando cada dado
bool
esTrue
, o cuando cada dadobool
esFalse
... ¡todos son iguales entre sí!
Por lo tanto, solo necesitamos encontrar dos elementos que evalúen diferentes
bool
spara saber que hay al menos uno
True
y al menos unoFalse
.Mi solución corta:
Creo que es un cortocircuito, porque AFAIK
a==b==c
es iguala==b and b==c
.Mi solución generalizada:
También escribí un código que trata con múltiples iterables, pero lo eliminé de aquí porque creo que no tiene sentido. Sin embargo, todavía está disponible aquí .
fuente
Esto es básicamente una funcionalidad de "algunos (pero no todos)" (en contraste con las funciones incorporadas
any()
yall()
).Esto implica que debe haber
False
s yTrue
s entre los resultados. Por lo tanto, puede hacer lo siguiente:Una ventaja de este código es que solo necesita iterar una vez a través de los elementos resultantes (booleanos).
Una desventaja es que todas estas expresiones de verdad siempre se evalúan y no hacen cortocircuitos como los operadores
or
/and
.fuente
.issuperset
lugar de solo verificar la longitud 2, debool
todos modos no puede devolver nada más que Verdadero y Falso? ¿Por qué asignar una lambda (léase: función anónima) a un nombre en lugar de simplemente usar un def?return
si se utilizadef
. Creo que la generalidad de esta solución es agradable. no es necesario restringirnos a los booleanos, la pregunta esencialmente es "¿cómo me aseguro de que todos estos elementos ocurran en mi lista". ¿Por quéset
si no necesitas la mutabilidad? Más inmutabilidad siempre es mejor si no necesita el rendimiento.tee
itertools.tee
pero 1) estaba buscando una línea que fuera simple / lo suficientemente pequeña como para justificar el pegado de copias, 2) ya dio una respuesta que usa esa técnica: -)