true negar bool python types boolean

negar - true or true python



En python, ¿hay algún tipo de mapeo para devolver el "valor falso" de un tipo? (5)

Estoy buscando algún tipo de función de mapeo f() que haga algo similar a esto:

f(str) = '''' f(complex) = 0j f(list) = []

Lo que significa que devuelve un objeto de tipo que se evalúa como False cuando se lo bool a bool .

¿Existe tal función?


Esto se llama realmente un elemento de identidad , y en la programación se ve más a menudo como parte de la definición de un monoid . En python, puede obtenerlo para un tipo usando la función mzero en el paquete PyMonad . Haskell lo llama mempty .


No existe tal función porque no es posible en general. Una clase puede no tener valor falso o puede requerir la inversión de una implementación arbitrariamente compleja de __bool__ .

Lo que podrías hacer rompiendo todo lo demás es construir un nuevo objeto de esa clase y asignar a la fuerza su función __bool__ a una que devuelva False . Aunque sospecho que estás buscando un objeto que de otro modo sería un miembro válido de la clase.

En cualquier caso, esta es una muy mala idea en estilo clásico.


No todos los tipos tienen tal valor para comenzar. Otros pueden tener muchos de esos valores. La forma más correcta de hacer esto sería crear un dict de tipo a valor, porque entonces podrías verificar si un tipo dado estaba en el dict, y podrías elegir qué valor es el correcto si hay múltiples opciones . El inconveniente es, por supuesto, que tendría que registrar de alguna manera cada tipo que le interese.

Alternativamente, podría escribir una función usando algunas heurísticas. Si tuvo mucho cuidado con lo que pasó a la función, probablemente sería de un uso limitado. Por ejemplo, todos los casos que muestra excepto complex son contenedores que se generalizan con cls() .

complex también funciona así, pero lo menciono por separado porque int y float no. Por lo tanto, si su intento con el constructor vacío falla devolviendo un objeto truey o provocando un TypeError , puede probar cls(0) . Y así sucesivamente y así sucesivamente...

Actualizar

La respuesta de @juanpa.arrivillaga en realidad sugiere una solución inteligente que funcionará para la mayoría de las clases. Puede ampliar la clase y crear a la fuerza una instancia que será falsa pero, por lo demás, idéntica a la clase original. Tienes que hacer esto extendiendo porque los métodos dunder como __bool__ solo se __bool__ en la clase, nunca en una instancia. También hay muchos tipos en los que tales métodos no pueden ser reemplazados en la instancia para comenzar. Como señala el comentario ahora borrado de @Aran-Fey, puede llamar selectivamente al object.__new__ o t.__new__ , dependiendo de si se trata de un caso muy especial (como int ) o no:

def f(t): class tx(t): def __bool__(self): return False try: return object.__new__(tx) except TypeError: return tx.__new__(tx)

Esto solo funcionará para el 99.9% de las clases que encuentres. Es posible crear un caso artificial que genere un TypeError cuando se pasa al object.__new__ como int does, y no permite una versión no-arg de t.__new__ , pero dudo que alguna vez lo encuentre en la naturaleza. Vea la gist @ Aran-Fey hecha para demostrar esto.


No, no hay tal mapeo. No todo tipo de objeto tiene un valor falso, y otros tienen más de uno. Como el valor de verdad de una clase se puede personalizar con el método __bool__ , una clase podría teóricamente tener un número infinito de instancias falsy (diferentes).

Dicho esto, la mayoría de los tipos incorporados devuelven su valor falsy cuando se llama a su constructor sin argumentos:

>>> str() '''' >>> complex() 0j >>> list() []


No, y en general, puede no haber tal valor. El modelo de datos de Python es bastante flexible sobre cómo se puede implementar el valor de verdad de un tipo:

object.__bool__(self)

Llamado para implementar pruebas de valor verdad y la operación incorporada bool (); debe devolver Falso o Verdadero. 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 ni __len__() ni __bool__() , todas sus instancias se consideran verdaderas.

Así que considere:

import random class Wacky: def __bool__(self): return bool(random.randint(0,1))

¿Qué debería devolver f(Wacky) ?