Como converter não tipo para inteiro ou string?

95

Eu tenho um Nonetypevalor x, geralmente é um número, mas poderia ser None. Quero dividir por um número, mas Python aumenta:

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

Como posso resolver isso?

user469652
fonte
5
Suponha que Nenhum é equivalente a 2771. Mas talvez não seja isso que você deseja. Por favor, dê mais informações.
JoshD
De alguma forma, obtive um valor Nonetype, que deveria ser um int, mas agora é um objeto Nonetype e preciso dividir outro número, então surgiu o erro.
user469652
int(None)lança uma exceção porque None não pode ser convertido em um int. A resposta à sua pergunta é que isso não pode ser feito. Você pode substituir algo, como 0, ou 2771, ou um elefante rosa, mas o que quer que você substitua, ainda não será capaz de converter Nenhum em um int.
snapshoe
7
@ ma3204. converter Nonepara um elefante rosa também não é bom, a menos que você esteja trabalhando em algum sistema numérico que defina formalmente a divisão de um número por um elefante rosa (e você tenha escrito o código para apoiá-lo)
aaronasterling

Respostas:

48

Em um dos comentários, você diz:

De alguma forma, obtive um valor Nonetype, que deveria ser um int, mas agora é um objeto Nonetype

Se for o seu código, descubra como você está recebendo Nonequando espera um número e evite que isso aconteça.

Se for o código de outra pessoa, descubra as condições sob as quais ele fornece Nonee determine um valor razoável a ser usado para isso, com o código condicional usual:

result = could_return_none(x)

if result is None:
    result = DEFAULT_VALUE

... ou mesmo ...

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.

Não há razão para usar 0aqui automaticamente - soluções que dependem do "falso" -ness de Noneassumir que você vai querer isso. O DEFAULT_VALUE(se existir) depende completamente do propósito do seu código.

detidamente
fonte
5
1 para a solução "certa". Se sua janela quebra com frequência misteriosamente, descubra o porquê (e pegue o vândalo responsável) em vez de bloquear a janela;)
3
Isso não é útil no caso de você estar recuperando chaves de um dicionário do Redis, por exemplo, pois as chaves ausentes serão Nenhuma. Se você quiser somar independentemente de sua presença (o que é um comportamento totalmente aceitável), pode ser necessário converter Nenhum para 0 (ver resposta kindall)
spider
1
@spider - isso ainda significa que é altamente dependente da situação, e "determinar um valor sensato" ainda se aplica.
detly
O ponto de Spider é bastante válido, esta resposta basicamente diz que você fez algo errado, mas Nenhum não significa que significa um valor desconhecido, que pode indicar que você fez algo errado, ou como o spider sugeriu um valor ausente, em geral deve ser 0 ou possivelmente 1, para a maioria dos usos possíveis de Nenhum onde um inteiro é esperado.
Glen Fletcher
@glenflet Se você não sabe qual é o domínio de entrada e as especificações de sua função, um estranho na Internet não será capaz de lhe dizer. Se você sabe, mas não conhece a sintaxe para convertê-lo, essa é uma pergunta completamente diferente da feita aqui.
detly
310
int(value or 0)

Isso usará 0 no caso em que você fornecer qualquer valor que o Python considere False, como Nenhum, 0, [], "", etc. Como 0 é False, você deve usar apenas 0 como o valor alternativo (caso contrário, você encontrará seus 0s transformando-se nesse valor).

int(0 if value is None else value)

Isso substitui apenas Nonepor 0. Como estamos testando Noneespecificamente, você pode usar algum outro valor como substituição.

kindall
fonte
64
user469652 você deve considerar tornar esta a resposta aceita. é realmente útil em oposição a condescendente
galarant
Não tenho certeza se isso resolve o problema que o usuário está enfrentando, ou seja. use o não-tipo para realizar um cálculo ... no momento, estou extraindo dados por meio de uma API de descanso que está retornando um não-tipo contendo um valor numérico. Se eu definir como 0 ou deixar como está, não posso fazer nada com ele
br3w5
2
Esta é certamente a melhor resposta, dada a questão, como o usuário indica que Nenhum, deve ser esperado, como possivelmente uma função, solicitando o valor de algo retornando Nenhum para indicar que o valor é desconhecido, neste caso, Nenhum deve se tornar o valor padrão em seu caso de uso, que normalmente seria 0. considere izip_longest, argumento padrão, se o diferente tiver um padrão diferente (tipo par), então o padrão deve ser Nenhum, que é então substituído por um padrão, porém string. <align_n> (str, w) leva apenas um inteiro para largura.
Glen Fletcher
2
Usei isso e ficou elegante e resolveu meus problemas.
Dan Safee
1
podemos usar (value or 0)- sem a conversão de tipo int - se
garantimos
16

Uma maneira comum "Pythônica" de lidar com esse tipo de situação é conhecida como EAFP para " É mais fácil pedir perdão do que permissão ". O que geralmente significa escrever um código que presuma que está tudo bem, mas depois embrulhá-lo com um try..exceptbloco apenas no caso de lidar com as coisas quando não está.

Este é o estilo de codificação aplicado ao seu problema:

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

answer = my_value / divisor

Ou talvez o ainda mais simples e um pouco mais rápido:

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

A abordagem inversa e mais tradicional é conhecida como LBYL, que significa " Olhe antes de pular " é o que @Soviut e alguns dos outros sugeriram. Para obter uma cobertura adicional deste tópico, consulte minha resposta e comentários associados à pergunta Determine se uma chave está presente em um dicionário em outro lugar deste site.

Um problema potencial com o EAFP é que ele pode ocultar o fato de que algo está errado com alguma outra parte do seu código ou módulo de terceiros que você está usando, especialmente quando as exceções ocorrem com frequência (e, portanto, não são casos realmente "excepcionais" em absoluto).

martineau
fonte
11

Isso TypeErrorsó aparece quando você tenta passar int() None(que é o único NoneTypevalor, pelo que eu sei). Eu diria que seu objetivo real não deve ser converter NoneTypepara intou str, mas descobrir onde / por que você está obtendo, em Nonevez de um número conforme o esperado, e corrigi-lo ou lidar com o Nonecorretamente.

paradoxo do waffle
fonte
Passar int()um número complexo, como int(1+2j), também fará com que TypeErrora seja aumentado, embora isso seja muito improvável. Independentemente disso, acho que você diria que seria, sem dúvida, um bom conselho a seguir.
martineau
5

No Python 3, você também pode usar a palavra-chave "ou". Deste jeito:

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

Usei com sucesso int (x ou 0) para este tipo de erro, desde que None deva ser igual a 0 na lógica. Observe que isso também será resolvido como 0 em outros casos em que o teste x retorna False. por exemplo, lista vazia, conjunto, dicionário ou string de comprimento zero. Desculpe, Kindall já deu esta resposta.

user3109122
fonte
1

Isso pode acontecer se você esquecer de retornar um valor de uma função: em seguida, retorna Nenhum. Observe todos os lugares onde você está atribuindo a essa variável e veja se um deles é uma chamada de função em que a função não possui uma instrução de retorno.

Jouni K. Seppänen
fonte
1
... ou a função tem uma ou mais instruções de retorno que são simples em returnvez de return some_expression.
John Machin,
... ou a função contém uma ou mais return Noneinstruções
John Machin,
1

Você deve verificar se o valor não é Nenhum antes de tentar realizar qualquer cálculo nele:

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

Nota: my_value foi intencionalmente definido como Nenhum para provar que o código funciona e que a verificação está sendo executada.

Soviut
fonte
1
você deve usar a comparação de identidade ( is [not] None)
shylent
-4 Você deve encorajar o OP a descobrir qual é o seu verdadeiro problema em vez de evitá-lo. O que @shylent disse. Você define my_valueincondicionalmente como Nenhum; porque? Você não questiona por que o OP pensa que precisa fazer int(my_value)quando my_valueé (se não nenhum) "geralmente um número".
John Machin,
1
Defino my_value como None como prova de conceito, para mostrar que meu código não falha. Não questionei o OP porque há muitos motivos pelos quais um valor nem sempre pode ser um número e verificar se é antes de realizar os cálculos é uma boa ideia. Não há nada de errado em simplesmente responder à pergunta do OP, eu não tenho que fazer todo o dever de casa para eles.
Soviut,
1

Eu estava tendo o mesmo problema ao usar as funções de e-mail do Python. Abaixo está o código que eu estava tentando recuperar o assunto do e-mail em uma variável. Isso funciona bem para a maioria dos e-mails e a variável é preenchida. Se você receber um e-mail do Yahoo ou similar e o remetente não preencher a linha de assunto, o Yahoo não criará uma linha de assunto no e-mail e você receberá um NoneType retornado da função. Martineau deu uma resposta correta, assim como Soviut. A resposta da IMO Soviut é mais concisa do ponto de vista da programação; não necessariamente de um Python. Aqui está um código para mostrar a 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
fonte
1

Em algumas situações, é útil ter uma função para converter None em int zero:

def nz(value):

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

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