Wie konvertiere ich Nonetype in int oder string?

95

Ich habe einen NonetypeWert x, es ist im Allgemeinen eine Zahl, könnte es aber sein None. Ich möchte es durch eine Zahl teilen, aber Python wirft:

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

Wie kann ich das lösen?

user469652
quelle
5
Angenommen, None entspricht 2771. Aber vielleicht ist es nicht das, was Sie wollen. Bitte geben Sie weitere Informationen.
JoshD
Irgendwie habe ich einen Nonetype-Wert erhalten, es sollte ein int sein, aber es ist jetzt ein Nonetype-Objekt, und ich muss eine andere Zahl teilen, dann ist der Fehler aufgetreten.
user469652
int(None)löst eine Ausnahme aus, da None nicht in ein int konvertiert werden kann. Die Antwort auf Ihre Frage ist, dass dies nicht möglich ist. Sie können etwas wie 0 oder 2771 oder einen rosa Elefanten ersetzen, aber was auch immer Sie ersetzen, Sie können None immer noch nicht in ein int konvertieren.
Snapshoe
7
@ ma3204. Die Konvertierung Nonein einen rosa Elefanten ist auch nicht gut, es sei denn, Sie arbeiten mit einem Zahlensystem, das die Division einer Zahl durch einen rosa Elefanten formal definiert (und Sie haben den Code geschrieben, um sie zu
sichern

Antworten:

48

In einem der Kommentare sagen Sie:

Irgendwie habe ich einen Nonetype-Wert bekommen, es sollte ein int sein, aber es ist jetzt ein Nonetype-Objekt

Wenn es Ihr Code, herauszufinden , wie Sie bekommen , Nonewenn Sie eine Nummer und Stopp erwarten , dass nicht passiert.

Wenn es sich um den Code eines anderen handelt, ermitteln Sie die Bedingungen, unter denen er angegeben ist, Noneund bestimmen Sie einen sinnvollen Wert, der dafür verwendet werden kann, mit dem üblichen bedingten Code:

result = could_return_none(x)

if result is None:
    result = DEFAULT_VALUE

...oder auch...

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.

Es gibt keinen Grund, hier automatisch zu verwenden 0- Lösungen, die von der "falschen" NoneAnnahme abhängen, dass Sie dies wollen. Das DEFAULT_VALUE(falls es überhaupt existiert) hängt vollständig vom Zweck Ihres Codes ab.

detly
quelle
5
+1 für die "richtige" Lösung. Wenn Ihr Fenster oft auf mysteriöse Weise bricht, finden Sie heraus, warum (und fangen Sie den verantwortlichen Vandalismus auf), anstatt das Fenster zu blockieren;)
3
Dies ist nicht nützlich, wenn Sie beispielsweise Schlüssel aus einem Redis-Wörterbuch abrufen, da die fehlenden Schlüssel Keine sind. Wenn Sie sie unabhängig von ihrer Anwesenheit summieren möchten (was ein völlig akzeptables Verhalten ist), müssen Sie möglicherweise None in 0 umwandeln (siehe Antwort)
spider
1
@spider - das bedeutet immer noch, dass es stark von der Situation abhängt und "einen vernünftigen Wert bestimmen" weiterhin gilt.
Detly
Der Punkt von Spider ist durchaus gültig. Diese Antwort besagt im Grunde nur, dass Sie etwas falsch gemacht haben, aber keiner bedeutet nicht, dass es einen unbekannten Wert bedeutet, der darauf hinweisen könnte, dass Sie etwas falsch gemacht haben, oder wie Spider einen fehlenden Wert vorgeschlagen hat, sollte er im Allgemeinen 0 sein oder möglicherweise 1 für die meisten möglichen Verwendungen von None, bei denen eine Ganzzahl erwartet wird.
Glen Fletcher
@glenflet Wenn Sie die Eingabedomäne und die Spezifikation Ihrer Funktion nicht kennen, kann Ihnen ein Fremder im Internet dies nicht sagen. Wenn Sie die Syntax für die Konvertierung kennen, aber nicht kennen, ist dies eine völlig andere Frage als die hier gestellte.
Detly
310
int(value or 0)

Dies wird 0 verwenden, wenn Sie einen von Python berücksichtigten Wert angeben False, z. B. None, 0, [], "" usw. Da 0 ist False, sollten Sie nur 0 als alternativen Wert verwenden (andernfalls finden Sie Ihre 0s in diesen Wert verwandeln).

int(0 if value is None else value)

Dies wird nur Nonedurch 0 ersetzt . Da wir Nonespeziell testen , können Sie einen anderen Wert als Ersatz verwenden.

irgendwie
quelle
64
user469652 Sie sollten in Betracht ziehen, dies stattdessen zur akzeptierten Antwort zu machen. Es ist tatsächlich hilfreich im Gegensatz zu herablassend
galarant
Ich bin nicht sicher, ob dies das Problem löst, mit dem der Benutzer konfrontiert ist, z. Verwenden Sie den Nicht-Typ, um eine Berechnung durchzuführen. Ich ziehe derzeit Daten über eine Rest-API ab, die einen Nicht-Typ zurückgibt, der einen numerischen Wert enthält. Wenn ich es auf 0 setze oder so lasse, wie es ist, kann ich nichts damit
anfangen
2
Dies ist trotz der Frage die beste Antwort, da der Benutzer angibt, dass None erwartet werden sollte, wie möglicherweise eine Funktion, die den Wert von etwas anfordert, das None zurückgibt, um anzuzeigen, dass der Wert unbekannt ist. In diesem Fall sollte None der Standardwert werden In seinem Anwendungsfall, der normalerweise 0 ist, ist izip_longest das Standardargument. Wenn das andere Argument einen anderen Standard (geraden Typ) hat, sollte der Standardwert None sein, der dann durch einen Standard ersetzt wird, jedoch eine Zeichenfolge. <align_n> (str, w) nimmt nur eine ganze Zahl für die Breite.
Glen Fletcher
2
Benutzte dies und es war elegant und löste meine Probleme.
Dan Safee
1
Wir können (value or 0)- ohne das Casting vom Typ int - verwenden, wenn wir versichert haben, dass der Wert nur ein None oder ein int
hashlash sein kann.
16

Eine übliche "pythonische" Methode, um mit dieser Art von Situation umzugehen, ist EAFP für " Es ist einfacher, um Vergebung zu bitten als um Erlaubnis ". Was normalerweise bedeutet, Code zu schreiben, der davon ausgeht, dass alles in Ordnung ist, und ihn dann mit einem try..exceptBlock zu umschließen, nur für den Fall, dass Dinge erledigt werden, wenn dies nicht der Fall ist.

Hier ist der Codierungsstil, der auf Ihr Problem angewendet wird:

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

answer = my_value / divisor

Oder vielleicht das noch einfachere und etwas schnellere:

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

Der umgekehrte und traditionellere Ansatz ist als LBYL bekannt und steht für " Look before you leap ", was @Soviut und einige der anderen vorgeschlagen haben. Weitere Informationen zu diesem Thema finden Sie in meiner Antwort und den zugehörigen Kommentaren zur Frage. Stellen Sie fest, ob ein Schlüssel in einem Wörterbuch an anderer Stelle auf dieser Site vorhanden ist.

Ein potenzielles Problem mit EAFP besteht darin, dass es die Tatsache verbergen kann, dass etwas mit einem anderen Teil Ihres Codes oder eines von Ihnen verwendeten Drittanbieter-Moduls nicht stimmt, insbesondere wenn die Ausnahmen häufig auftreten (und daher keine wirklich "Ausnahmefälle" sind überhaupt).

Martineau
quelle
11

Das TypeErrorerscheint nur, wenn Sie versuchen zu bestehen int() None(was meines Wissens der einzige NoneTypeWert ist). Ich würde sagen, dass Ihr eigentliches Ziel nicht darin bestehen sollte, NoneTypenach intoder zu konvertieren str, sondern herauszufinden, woher / warum Sie Noneanstelle einer Zahl wie erwartet kommen, und diese entweder zu korrigieren oder Nonerichtig zu handhaben .

Waffelparadoxon
quelle
Das Übergeben int()einer komplexen Zahl, wie z. B. int(1+2j), führt ebenfalls zu einer TypeErrorErhöhung, obwohl dies zugegebenermaßen wahrscheinlich sehr unwahrscheinlich ist. Unabhängig davon denke ich, dass Sie sagen, dass dies ohne Frage im Allgemeinen ein guter Rat wäre, dem Sie folgen sollten.
Martineau
5

In Python 3 können Sie auch das Schlüsselwort "oder" verwenden. Diesen Weg:

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

Ich habe int (x oder 0) erfolgreich für diesen Fehlertyp verwendet, solange None in der Logik gleich 0 sein sollte. Beachten Sie, dass dies auch in anderen Fällen auf 0 aufgelöst wird, in denen das Testen von x False zurückgibt. zB leere Liste, Satz, Wörterbuch oder Zeichenfolge mit der Länge Null. Entschuldigung, Kindall hat diese Antwort bereits gegeben.

user3109122
quelle
1

Dies kann passieren, wenn Sie vergessen, einen Wert von einer Funktion zurückzugeben: Dann wird None zurückgegeben. Sehen Sie sich alle Stellen an, an denen Sie dieser Variablen zuweisen, und prüfen Sie, ob es sich bei einer davon um einen Funktionsaufruf handelt, bei dem der Funktion eine return-Anweisung fehlt.

Jouni K. Seppänen
quelle
1
... oder die Funktion hat eine oder mehrere return-Anweisungen, die einfach nur returnstatt sind return some_expression.
John Machin
... oder die Funktion enthält eine oder mehrere return NoneAnweisungen
John Machin
1

Sie sollten überprüfen, ob der Wert nicht None ist, bevor Sie versuchen, Berechnungen daran durchzuführen:

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

Hinweis: my_value wurde absichtlich auf Keine gesetzt, um zu beweisen, dass der Code funktioniert und die Prüfung durchgeführt wird.

Soviut
quelle
1
Sie sollten den Identitätsvergleich ( is [not] None) verwenden
shylent
-4 Sie sollten das OP ermutigen, herauszufinden, was sein eigentliches Problem ist, anstatt es zu vermeiden. Was @shylent gesagt hat. Sie setzen my_valuebedingungslos auf Keine; Warum? Sie fragen sich nicht, warum das OP glaubt, dass er etwas tun muss, int(my_value)wenn my_value(wenn nicht gar keine) "im Allgemeinen eine Zahl" ist.
John Machin
1
Ich habe my_value als Proof of Concept auf None gesetzt, um zu zeigen, dass mein Code nicht fehlschlägt. Ich habe das OP nicht in Frage gestellt, da es viele Gründe gibt, warum ein Wert möglicherweise nicht immer eine Zahl ist. Es ist eine gute Idee, dies zu überprüfen, bevor Berechnungen durchgeführt werden. Es ist nichts Falsches daran, einfach die Frage des OP zu beantworten. Ich muss nicht alle Hausaufgaben für sie machen.
Soviut
1

Ich hatte das gleiche Problem mit den Python-E-Mail-Funktionen. Unten ist der Code, den ich versucht habe, den Betreff einer E-Mail in eine Variable abzurufen. Dies funktioniert für die meisten E-Mails einwandfrei und die Variable wird ausgefüllt. Wenn Sie eine E-Mail von Yahoo oder ähnlichem erhalten und der Absender die Betreffzeile nicht ausgefüllt hat, erstellt Yahoo keine Betreffzeile in der E-Mail und Sie erhalten von der Funktion einen NoneType zurück. Martineau gab eine richtige Antwort sowie Soviut. Die Antwort von IMO Soviut ist vom Standpunkt der Programmierung aus prägnanter. nicht unbedingt von einem Python. Hier ist ein Code, der die Technik zeigt:

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
quelle
1

In einigen Situationen ist es hilfreich, eine Funktion zum Konvertieren von None in int zero zu haben:

def nz(value):

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

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