¿Cómo convertir Nonetype a int o string?

96

Tengo un Nonetypevalor x, generalmente es un número, pero podría serlo None. Quiero dividirlo por un número, pero Python aumenta:

TypeError: int() argument must be a string or a number, not 'NoneType'

¿Como puedo resolver esto?

usuario469652
fuente
5
Suponga que None es equivalente a 2771. Pero tal vez eso no sea lo que desea. Proporcione más información.
JoshD
De alguna manera obtuve un valor Nonetype, se supone que es un int, pero ahora es un objeto Nonetype, y necesito dividir otro número, luego apareció el error.
user469652
int(None)lanza una excepción porque None no se puede convertir en un int. La respuesta a tu pregunta es que no se puede hacer. Puede sustituir algo, como 0 o 2771, o un elefante rosa, pero lo que sea que sustituya, no podrá convertir None en un int.
zapato de presión
7
@ ma3204. convertirse Noneen un elefante rosa tampoco es bueno, a menos que esté trabajando en algún sistema numérico que defina formalmente la división de un número por un elefante rosa (y haya escrito el código para respaldarlo)
aaronasterling

Respuestas:

49

En uno de los comentarios, dices:

De alguna manera obtuve un valor Nonetype, se supone que es un int, pero ahora es un objeto Nonetype

Si es su código, averigüe cómo está obteniendo Nonecuando espera un número y evite que eso suceda.

Si es el código de otra persona, averigüe las condiciones bajo las cuales se da Noney determine un valor razonable para usarlo, con el código condicional habitual:

result = could_return_none(x)

if result is None:
    result = DEFAULT_VALUE

...o incluso...

if x == THING_THAT_RESULTS_IN_NONE:
    result = DEFAULT_VALUE
else:
    result = could_return_none(x) # But it won't return None, because we've restricted the domain.

No hay razón para usar automáticamente 0aquí - soluciones que dependen de la "falsedad" - de Noneasumir que querrás esto. El DEFAULT_VALUE(si es que existe) depende completamente del propósito de su código.

detenidamente
fuente
5
+1 para la solución "correcta". Si su ventana a menudo se rompe misteriosamente, averigüe por qué (y atrape al vándalo responsable) en lugar de bloquear la ventana;)
3
Esto no es útil en caso de que esté recuperando claves de un diccionario de Redis, por ejemplo, ya que las claves que faltan serán Ninguna. Si desea sumarlos independientemente de su presencia (que es un comportamiento totalmente aceptable), es posible que deba convertir Ninguno en 0 (vea la respuesta un poco)
spider
1
@spider: eso aún significa que depende en gran medida de la situación y aún se aplica "determinar un valor razonable".
detly
El punto de Spider es bastante válido, esta respuesta básicamente solo dice que hiciste algo mal, pero Ninguno no significa que signifique un valor desconocido, eso podría indicar que hiciste algo mal, o como Spider sugirió un valor faltante, en general debería ser 0 o posiblemente 1, para la mayoría de los usos posibles de None donde se espera un número entero.
Glen Fletcher
@glenflet Si no sabe cuál es el dominio de entrada y la especificación de su función, un extraño en Internet no podrá decírselo. Si lo sabe, pero no conoce la sintaxis para convertirlo, esa es una pregunta completamente diferente a la que se hace aquí.
detly
312
int(value or 0)

Esto usará 0 en el caso de que proporciones cualquier valor que Python considere False, como Ninguno, 0, [], "", etc. Dado que 0 es False, solo debes usar 0 como valor alternativo (de lo contrario, encontrarás tus 0s convirtiéndose en ese valor).

int(0 if value is None else value)

Esto se reemplaza solo Nonecon 0. Dado que estamos probando Noneespecíficamente, puede usar algún otro valor como reemplazo.

un poco
fuente
64
user469652 debería considerar hacer que esta sea la respuesta aceptada. en realidad es muy útil en comparación con condescendencia
galarant
No estoy seguro de si esto resuelve el problema al que se enfrenta el usuario, es decir. use el nonetype para realizar un cálculo ... actualmente estoy extrayendo datos a través de una api de descanso que devuelve un nonetype que contiene un valor numérico. Si lo configuro en 0 o lo dejo como está, no puedo hacer nada con él
br3w5
2
Definitivamente, esta es la mejor respuesta, dada la pregunta, ya que el usuario indica que se debe esperar None, como posiblemente una función, solicitando el valor de algo que devuelve None para indicar que el valor es desconocido, en este caso, None debería convertirse en el valor predeterminado en su caso de uso, que normalmente sería 0. considere izip_longest, argumento predeterminado, si el diferente tiene un valor predeterminado diferente (tipo par), entonces el valor predeterminado debería ser Ninguno, que luego se reemplaza con un valor predeterminado, sin embargo, una cadena. <align_n> (str, w) solo toma un número entero para el ancho.
Glen Fletcher
2
Usé esto y fue elegante y resolvió mis problemas.
Dan Safee
1
podemos usar (value or 0), sin la conversión de tipo int, si aseguramos que el valor solo puede ser None o int
hashlash
16

Una forma "Pythonic" común de manejar este tipo de situación se conoce como EAFP por " Es más fácil pedir perdón que permiso ". Lo que generalmente significa escribir código que asume que todo está bien, pero luego envolverlo con un try..exceptbloque por si acaso para manejar las cosas cuando no lo está.

Aquí está ese estilo de codificación aplicado a su problema:

try:
    my_value = int(my_value)
except TypeError:
    my_value = 0  # or whatever you want to do

answer = my_value / divisor

O quizás el más simple y un poco más rápido:

try:
    answer = int(my_value) / divisor
except TypeError:
    answer = 0

El enfoque inverso y más tradicional se conoce como LBYL, que significa " Mira antes de saltar ", es lo que han sugerido @Soviut y algunos de los otros. Para obtener información adicional sobre este tema, consulte mi respuesta y los comentarios asociados a la pregunta Determinar si una clave está presente en un diccionario en otra parte de este sitio.

Un problema potencial con EAFP es que puede ocultar el hecho de que algo está mal con alguna otra parte de su código o módulo de terceros que está utilizando, especialmente cuando las excepciones ocurren con frecuencia (y por lo tanto no son casos realmente "excepcionales" en absoluto).

martineau
fuente
11

Eso TypeErrorsolo aparece cuando intentas pasar int() None(que es el único NoneTypevalor, hasta donde yo sé). Yo diría que su objetivo real no debería ser convertir NoneTypea into str, sino averiguar dónde / por qué está obteniendo en Nonelugar de un número como se esperaba, y solucionarlo o manejarlo Nonecorrectamente.

paradoja de la galleta
fuente
Pasar int()un número complejo, como int(1+2j), también hará TypeErrorque se aumente, aunque hay que admitir que es muy poco probable. Independientemente, creo que dices que sería, sin lugar a dudas, un buen consejo a seguir.
martineau
5

En Python 3 también puede usar la palabra clave "o". De esta manera:

foo = bar or 0
foo2 = bar or ""
Ferrarezi
fuente
2

He utilizado con éxito int (xo 0) para este tipo de error, siempre que Ninguno sea igual a 0 en la lógica. Tenga en cuenta que esto también se resolverá en 0 en otros casos en los que probar x devuelve False. por ejemplo, lista vacía, conjunto, diccionario o cadena de longitud cero. Lo siento, Kindall ya dio esta respuesta.

usuario3109122
fuente
1

Esto puede suceder si olvida devolver un valor de una función: luego devuelve Ninguno. Mire todos los lugares donde está asignando a esa variable y vea si uno de ellos es una llamada de función donde la función carece de una declaración de retorno.

Jouni K. Seppänen
fuente
1
... o la función tiene una o más declaraciones de retorno que son simples en returnlugar de return some_expression.
John Machin
... o la función contiene una o más return Nonedeclaraciones
John Machin
1

Debe verificar para asegurarse de que el valor no sea Ninguno antes de intentar realizar cualquier cálculo en él:

my_value = None
if my_value is not None:
    print int(my_value) / 2

Nota: my_value se estableció intencionalmente en Ninguno para probar que el código funciona y que se está realizando la verificación.

Soviut
fuente
1
debe usar la comparación de identidad ( is [not] None)
shylent
-4 Debería alentar al OP a descubrir cuál es su problema real en lugar de evitarlo. Lo que dijo @shylent. Establece my_valueincondicionalmente en Ninguno; ¿por qué? No se cuestiona por qué el OP cree que debe hacerlo int(my_value)cuando my_valuees (si no Ninguno) "generalmente un número".
John Machin
1
Establecí my_value en None como prueba de concepto, para mostrar que mi código no falla. No cuestioné el OP porque hay muchas razones por las que un valor no siempre puede ser un número y verificar que lo sea antes de realizar los cálculos es una buena idea. No hay nada de malo en simplemente responder la pregunta del OP, no tengo que hacer toda la tarea por ellos.
Soviut
1

Estaba teniendo el mismo problema al usar las funciones de correo electrónico de Python. A continuación se muestra el código que estaba tratando de recuperar el asunto del correo electrónico en una variable. Esto funciona bien para la mayoría de los correos electrónicos y la variable se completa. Si recibe un correo electrónico de Yahoo o similar y el remitente no completó la línea de asunto, Yahoo no crea una línea de asunto en el correo electrónico y obtiene un NoneType devuelto por la función. Martineau proporcionó una respuesta correcta al igual que Soviut. La respuesta de IMO Soviut es más concisa desde el punto de vista de la programación; no necesariamente de uno de Python. Aquí hay un código para mostrar la técnica:

import sys, email, email.Utils 

afile = open(sys.argv[1], 'r')    
m = email.message_from_file(afile)    
subject = m["subject"]

# Soviut's Concise test for unset variable.

if subject is None:    
     subject = "[NO SUBJECT]"

# Alternative way to test for No Subject created in email (Thanks for NoneThing Yahoo!)

try:    
    if len(subject) == 0:    
        subject = "[NO SUBJECT]"

except TypeError:    
    subject = "[NO SUBJECT]"

print subject

afile.close()
George Pearson
fuente
1

En algunas situaciones, es útil tener una función para convertir None en int cero:

def nz(value):

    '''
    Convert None to int zero else return value.
    '''

    if value == None:
        return 0
    return value
user2920482
fuente