Comment convertir Nonetype en int ou string?

96

J'ai une Nonetypevaleur x, c'est généralement un nombre, mais ça pourrait l'être None. Je veux le diviser par un nombre, mais Python soulève:

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

Comment puis-je resoudre ceci?

user469652
la source
5
Supposons que None équivaut à 2771. Mais ce n'est peut-être pas ce que vous voulez. Veuillez donner plus d'informations.
JoshD
D'une manière ou d'une autre, j'ai obtenu une valeur Nonetype, supposée être un int, mais c'est maintenant un objet Nonetype, et j'ai besoin de diviser un autre nombre, puis l'erreur est survenue.
user469652
int(None)lève une exception car None ne peut pas être converti en int. La réponse à votre question est que cela ne peut pas être fait. Vous pouvez remplacer quelque chose, comme 0 ou 2771, ou un éléphant rose, mais quoi que vous remplaciez, vous ne pourrez toujours pas convertir None en int.
snapshoe
7
@ ma3204. se convertir Noneen éléphant rose n'est pas bon non plus, à moins que vous ne travailliez sur un système de numération qui définit formellement la division d'un nombre par un éléphant rose (et que vous avez écrit le code pour le sauvegarder)
aaronasterling

Réponses:

49

Dans l'un des commentaires, vous dites:

D'une manière ou d'une autre, j'ai une valeur Nonetype, supposée être un int, mais c'est maintenant un objet Nonetype

Si c'est votre code, déterminez comment vous obtenez Nonelorsque vous attendez un numéro et empêchez cela de se produire.

Si c'est le code de quelqu'un d'autre, découvrez les conditions dans lesquelles il donne Noneet déterminez une valeur sensible à utiliser pour cela, avec le code conditionnel habituel:

result = could_return_none(x)

if result is None:
    result = DEFAULT_VALUE

...ou même...

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.

Il n'y a aucune raison d'utiliser automatiquement 0ici - des solutions qui dépendent de la "fausse" -ness de Nonesupposer que vous voudrez cela. Le DEFAULT_VALUE(s'il existe même) dépend complètement de l'objectif de votre code.

detly
la source
5
+1 pour la «bonne» solution. Si votre fenêtre se brise souvent mystérieusement, découvrez pourquoi (et attrapez le vandale qui est responsable) au lieu de bloquer la fenêtre;)
3
Cela n'est pas utile dans le cas où vous récupérez des clés d'un dictionnaire Redis par exemple, car les clés manquantes seront Aucune. Si vous voulez les additionner indépendamment de leur présence (ce qui est un comportement tout à fait acceptable), vous devrez peut-être convertir Aucun en 0 (voir la réponse du genre)
araignée
1
@spider - cela signifie toujours qu'il dépend fortement de la situation et que "déterminer une valeur sensible" s'applique toujours.
detly
Le point de Spider est tout à fait valable, cette réponse dit simplement que vous avez fait quelque chose de mal, mais Aucun ne signifie pas que cela signifie une valeur inconnue, cela pourrait indiquer que vous avez fait quelque chose de mal, ou comme l'araignée a suggéré une valeur manquante, en général, elle devrait être 0 ou éventuellement 1, pour la plupart des utilisations possibles de None où un entier est attendu.
Glen Fletcher
@glenflet Si vous ne savez pas quel est le domaine d'entrée et la spécification de votre fonction, un inconnu sur Internet ne pourra pas vous le dire. Si vous savez, mais ne connaissez pas la syntaxe pour le convertir, c'est une question complètement différente de celle posée ici.
detly
312
int(value or 0)

Cela utilisera 0 dans le cas où vous fournissez une valeur que Python considère False, telle que None, 0, [], "", etc. Puisque 0 est False, vous ne devriez utiliser que 0 comme valeur alternative (sinon vous trouverez vos 0 devenir cette valeur).

int(0 if value is None else value)

Cela remplace uniquement Nonepar 0. Puisque nous testons Nonespécifiquement, vous pouvez utiliser une autre valeur comme remplacement.

kindall
la source
64
user469652, vous devriez envisager d'en faire la réponse acceptée à la place. c'est en fait utile plutôt que condescendant
galarant
Je ne suis pas sûr que cela résout le problème auquel l'utilisateur est confronté. utilisez le nonetype pour effectuer un calcul ... je tire actuellement des données via une API de repos qui renvoie un non-type contenant une valeur numérique. Si je le
mets
2
C'est sans aucun doute la meilleure réponse, étant donné la question, car l'utilisateur indique que None, devrait être attendu, comme peut-être une fonction, demandant la valeur de quelque chose retournant None pour indiquer que la valeur est inconnue dans ce cas, None devrait devenir la valeur par défaut dans son cas d'utilisation, qui serait généralement 0. considérez izip_longest, argument par défaut, si le différent a une valeur par défaut différente (même type), alors la valeur par défaut devrait être None qui est alors remplacée par une valeur par défaut, cependant une chaîne. <align_n> (str, w) ne prend qu'un entier pour la largeur.
Glen Fletcher
2
Utilisé ceci et c'était élégant et a résolu mes problèmes.
Dan Safee
1
nous pouvons utiliser (value or 0)- sans le casting de type int - si nous assurons que la valeur ne peut être qu'un None ou un int
hashlash
16

Une manière «pythonique» courante de gérer ce genre de situation est connue sous le nom d' EAFP pour « Il est plus facile de demander pardon que la permission ». Ce qui signifie généralement écrire du code qui suppose que tout va bien, mais ensuite l'envelopper avec un try..exceptbloc au cas où il faudrait gérer les choses quand ce n'est pas le cas.

Voici ce style de codage appliqué à votre problème:

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

answer = my_value / divisor

Ou peut-être le plus simple et légèrement plus rapide:

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

L'approche inverse et plus traditionnelle est connue sous le nom de LBYL qui signifie « Regardez avant de sauter », c'est ce que @Soviut et certains autres ont suggéré. Pour une couverture supplémentaire de ce sujet, consultez ma réponse et les commentaires associés à la question Déterminez si une clé est présente dans un dictionnaire ailleurs sur ce site.

Un problème potentiel avec EAFP est qu'il peut masquer le fait que quelque chose ne va pas avec une autre partie de votre code ou du module tiers que vous utilisez, en particulier lorsque les exceptions se produisent fréquemment (et ne sont donc pas vraiment des cas "exceptionnels" du tout).

Martineau
la source
11

Cela TypeErrorn'apparaît que lorsque vous essayez de passer int() None(ce qui est la seule NoneTypevaleur, pour autant que je sache). Je dirais que votre véritable objectif ne devrait pas être de convertir NoneTypeen intou str, mais de déterminer où / pourquoi vous obtenez Noneau lieu d'un nombre comme prévu, et de le réparer ou de le gérer Nonecorrectement.

paradoxe de la gaufre
la source
Passer int()un nombre complexe, tel que int(1+2j), entraînera également une TypeErroraugmentation de a, bien que cela soit probablement très improbable. Quoi qu'il en soit, je pense que vous dites serait, sans aucun doute, généralement un bon conseil à suivre.
martineau
5

Dans Python 3, vous pouvez également utiliser le mot-clé "ou". Par ici:

foo = bar or 0
foo2 = bar or ""
Ferrarezi
la source
2

J'ai utilisé avec succès int (x ou 0) pour ce type d'erreur, tant que None devrait être égal à 0 dans la logique. Notez que cela sera également résolu à 0 dans d'autres cas où le test de x renvoie False. par exemple, liste vide, ensemble, dictionnaire ou chaîne de longueur nulle. Désolé, Kindall a déjà donné cette réponse.

user3109122
la source
1

Cela peut arriver si vous oubliez de renvoyer une valeur à partir d'une fonction: il renvoie alors None. Regardez tous les endroits où vous affectez à cette variable et voyez si l'un d'eux est un appel de fonction où la fonction n'a pas d'instruction de retour.

Jouni K. Seppänen
la source
1
... ou la fonction a une ou plusieurs instructions de retour qui sont simplement simples à la returnplace de return some_expression.
John Machin
... ou la fonction contient une ou plusieurs return Noneinstructions
John Machin
1

Vous devez vérifier que la valeur n'est pas None avant d'essayer d'effectuer des calculs dessus:

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

Remarque: a my_value été intentionnellement défini sur Aucun pour prouver que le code fonctionne et que la vérification est en cours.

Soviut
la source
1
vous devriez utiliser la comparaison d'identité ( is [not] None)
shylent
-4 Vous devriez encourager le PO à découvrir quel est son vrai problème au lieu de l'éviter. Ce que @shylent a dit. Vous définissez my_valueinconditionnellement sur Aucun; Pourquoi? Vous ne vous demandez pas pourquoi l'OP pense qu'il doit faire int(my_value)quand my_valueest (sinon Aucun) "généralement un nombre".
John Machin
1
J'ai mis my_value à None comme preuve de concept, pour montrer que mon code n'échoue pas. Je n'ai pas remis en question l'OP car il existe de nombreuses raisons pour lesquelles une valeur peut ne pas toujours être un nombre et vérifier qu'elle l'est avant d'effectuer des calculs est une bonne idée. Il n'y a rien de mal à répondre simplement à la question du PO, je n'ai pas à faire tous leurs devoirs à leur place.
Soviut
1

J'avais le même problème en utilisant les fonctions de messagerie python. Vous trouverez ci-dessous le code que j'essayais de récupérer l'objet de l'e-mail dans une variable. Cela fonctionne bien pour la plupart des e-mails et la variable se remplit. Si vous recevez un e-mail de Yahoo ou autre et que l'expéditeur n'a pas rempli la ligne d'objet, Yahoo ne crée pas de ligne d'objet dans l'e-mail et vous obtenez un NoneType renvoyé par la fonction. Martineau a fourni une réponse correcte ainsi que Soviut. La réponse de l'OMI Soviut est plus concise du point de vue de la programmation; pas nécessairement d'un Python. Voici un code pour montrer la technique:

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
la source
1

Dans certaines situations, il est utile d'avoir une fonction pour convertir None en int zéro:

def nz(value):

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

    if value == None:
        return 0
    return value
user2920482
la source