Jak przekonwertować Nonetype na int lub string?

98

Mam Nonetypewartość x, generalnie jest to liczba, ale może być None. Chcę to podzielić przez liczbę, ale Python podnosi:

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

Jak mogę to rozwiązać?

user469652
źródło
5
Załóżmy, że Brak jest odpowiednikiem 2771. Ale może nie tego chcesz. Proszę podać więcej informacji.
JoshD,
W jakiś sposób uzyskałem wartość Nonetype, przypuszczalnie jest to int, ale teraz jest to obiekt Nonetype i muszę podzielić inną liczbę, a potem pojawił się błąd.
user469652
int(None)zgłasza wyjątek, ponieważ None nie może zostać przekonwertowana na int. Odpowiedź na Twoje pytanie brzmi: nie da się tego zrobić. Możesz podstawić coś, na przykład 0, 2771 lub różowego słonia, ale cokolwiek zastąpisz, nadal nie będziesz w stanie przekonwertować None na int.
snapshoe
7
@ ma3204. konwersja Nonena różowego słonia też nie jest dobra, chyba że pracujesz nad jakimś systemem liczbowym, który formalnie definiuje dzielenie liczby przez różowego słonia (i napisałeś kod, aby ją wykonać)
aaronasterling

Odpowiedzi:

49

W jednym z komentarzy mówisz:

W jakiś sposób otrzymałem wartość Nonetype, przypuszczalnie to int, ale teraz jest to obiekt Nonetype

Jeśli to twój kod, dowiedz się, jak otrzymujesz, Nonekiedy spodziewasz się liczby, i powstrzymaj to .

Jeśli jest to kod kogoś innego, dowiedz się, w jakich warunkach daje Nonei określ sensowną wartość do użycia, używając zwykłego kodu warunkowego:

result = could_return_none(x)

if result is None:
    result = DEFAULT_VALUE

...lub nawet...

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.

Nie ma powodu, aby używać 0tutaj automatycznie - rozwiązań, które zależą od „fałszywego” Nonezałożenia, że ​​będziesz tego chciał. DEFAULT_VALUE(Jeśli w ogóle istnieje) całkowicie zależy od celu w kodzie.

bezczelnie
źródło
5
+1 za „właściwe” rozwiązanie. Jeśli twoje okno często w tajemniczy sposób pęka, dowiedz się, dlaczego (i złap wandala, który jest odpowiedzialny) zamiast blokować okno;)
3
Nie jest to przydatne na przykład w przypadku pobierania kluczy ze słownika redis, ponieważ brakującymi kluczami będą Brak. Jeśli chcesz je zsumować niezależnie od ich obecności (co jest całkowicie akceptowalnym zachowaniem), może być konieczne przekonwertowanie None na 0 (zobacz odpowiedź kindall)
pająk
1
@spider - to nadal oznacza, że ​​jest wysoce zależny od sytuacji, a „określ rozsądną wartość” nadal ma zastosowanie.
detly
Argument pająka jest całkiem słuszny, ta odpowiedź po prostu mówi, że zrobiłeś coś źle, ale Brak nie oznacza, że ​​oznacza to nieznaną wartość, która może wskazywać, że zrobiłeś coś źle, lub ponieważ pająk zasugerował brakującą wartość, generalnie powinna być 0 lub ewentualnie 1, dla większości możliwych zastosowań None, gdzie oczekiwana jest liczba całkowita.
Glen Fletcher
@glenflet Jeśli nie wiesz, jaka jest domena wejściowa i specyfikacja Twojej funkcji, obcy w Internecie nie będzie w stanie Ci tego powiedzieć. Jeśli wiesz, ale nie znasz składni konwersji, to jest to zupełnie inne pytanie niż zadane tutaj.
detly
318
int(value or 0)

Spowoduje to użycie 0 w przypadku, gdy podasz jakąkolwiek wartość uznaną przez Pythona False, taką jak Brak, 0, [], "" itd. Ponieważ 0 to False, powinieneś używać tylko 0 jako wartości alternatywnej (w przeciwnym razie znajdziesz swoje 0 zamieniając się w tę wartość).

int(0 if value is None else value)

To zastępuje tylko None0. Ponieważ testujemy Nonekonkretnie, możesz użyć innej wartości jako zamiennika.

kindall
źródło
65
user469652, zamiast tego powinieneś rozważyć zaakceptowanie tej odpowiedzi. jest rzeczywiście pomocny w przeciwieństwie do protekcjonalnego
galarant
Nie jestem pewien, czy to rozwiązuje problem, z którym boryka się użytkownik, tj. użyj typu nonetype do wykonania obliczeń ... obecnie pobieram dane za pośrednictwem interfejsu API REST, który zwraca wartość typu nonetype zawierającą wartość liczbową. Jeśli
ustawię
2
Jest to zdecydowanie najlepsza odpowiedź, biorąc pod uwagę pytanie, ponieważ użytkownik wskazuje, że należy się spodziewać None, podobnie jak prawdopodobnie funkcji, żądającej wartości czegoś zwracającego None, aby wskazać, że wartość jest nieznana, w tym przypadku None powinno stać się wartością domyślną w jego przypadku użycia, który zwykle wynosi 0. rozważ izip_longest, domyślny argument, jeśli inny ma inny domyślny (parzysty typ), to domyślnym powinno być Brak, który jest następnie zastępowany domyślnym, jednak ciągiem. <align_n> (str, w) przyjmuje tylko liczbę całkowitą jako szerokość.
Glen Fletcher
2
Użyłem tego i było eleganckie i rozwiązało moje problemy.
Dan Safee
1
możemy użyć (value or 0)- bez rzutowania typu int - jeśli zapewnimy, że wartość może być tylko wartością None lub int
hashlash
17

Powszechny „Pythonowy” sposób radzenia sobie z tego rodzaju sytuacjami jest znany jako EAFP, czyliłatwiej prosić o przebaczenie niż o pozwolenie ”. Co zwykle oznacza napisanie kodu, który zakłada, że ​​wszystko jest w porządku, ale następnie owinięcie go try...exceptblokiem do obsługi rzeczy - tak na wszelki wypadek - tak nie jest.

Oto styl kodowania zastosowany do Twojego problemu:

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

answer = my_value / divisor

A może jeszcze prostszy i nieco szybszy:

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

Odwrotne i bardziej tradycyjne podejście jest znane jako LBYL, co oznacza „ Look before you leap ”, co zasugerował @Soviut i niektórzy inni. Aby uzyskać dodatkowe omówienie tego tematu, zobacz moją odpowiedź i powiązane komentarze do pytania Ustal, czy klucz znajduje się w słowniku w innym miejscu na tej stronie.

Jednym z potencjalnych problemów z EAFP jest to, że może on ukryć fakt, że coś jest nie tak z inną częścią twojego kodu lub modułem innej firmy, z której korzystasz, zwłaszcza gdy często występują wyjątki (i dlatego nie są to naprawdę „wyjątkowe” przypadki w ogóle).

martineau
źródło
11

Że TypeErrorpojawia się tylko wtedy, gdy próbujesz przekazać int() None(który jest tylko NoneTypewartość, o ile wiem). Powiedziałbym, że Twoim prawdziwym celem nie powinno być przekonwertowanie NoneTypena intlub str, ale Noneustalenie , gdzie / dlaczego otrzymujesz zamiast liczby zgodnie z oczekiwaniami, i albo napraw go, albo Noneodpowiednio obsłuż.

paradoks gofrów
źródło
Przekazanie int()liczby zespolonej, takiej jak int(1+2j), również spowoduje TypeErrorpodniesienie a, chociaż trzeba przyznać, że jest to prawdopodobnie bardzo mało prawdopodobne. Niezależnie od tego, myślę, że powiedziałbyś, że bez wątpienia byłaby to ogólnie dobra rada do naśladowania.
martineau
5

W Pythonie 3 możesz również użyć słowa kluczowego „lub”. Tą drogą:

foo = bar or 0
foo2 = bar or ""
Ferrarezi
źródło
2

Z powodzeniem użyłem int (x lub 0) dla tego typu błędu, o ile None powinien być równy 0 w logice. Zauważ, że rozwiąże to również do 0 w innych przypadkach, gdy testowanie x zwraca False. np. pusta lista, zbiór, słownik lub łańcuch o zerowej długości. Przepraszamy, Kindall już udzielił tej odpowiedzi.

user3109122
źródło
1

Może się to zdarzyć, jeśli zapomnisz zwrócić wartość z funkcji: zwraca ona wtedy None. Spójrz na wszystkie miejsca, w których przypisujesz tę zmienną, i zobacz, czy jedno z nich jest wywołaniem funkcji, w którym funkcja nie zawiera instrukcji return.

Jouni K. Seppänen
źródło
1
... lub funkcja ma jedną lub więcej instrukcji return, które są po prostu zwykłe returnzamiast return some_expression.
John Machin,
... lub funkcja zawiera jedną lub więcej return Noneinstrukcji
John Machin,
1

Przed wykonaniem jakichkolwiek obliczeń należy sprawdzić, czy wartość nie jest ustawiona na Brak:

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

Uwaga: my_value celowo ustawiono wartość Brak, aby udowodnić, że kod działa i że sprawdzanie jest wykonywane.

Soviut
źródło
1
powinieneś użyć porównania tożsamości ( is [not] None)
shylent
-4 Powinieneś zachęcać OP, aby dowiedział się, jaki jest jego prawdziwy problem, zamiast go unikać. Co powiedział @shylent. Ustawić my_valuebezwarunkowo None; czemu? Nie zastanawiasz się, dlaczego OP uważa, że ​​musi to zrobić, int(my_value)kiedy my_value(jeśli nie Brak) „ogólnie jest liczbą”.
John Machin
1
Ustawiłem my_value na None jako dowód koncepcji, aby pokazać, że mój kod nie zawodzi. Nie kwestionowałem OP, ponieważ istnieje wiele powodów, dla których wartość może nie zawsze być liczbą i sprawdzenie, czy jest przed wykonaniem obliczeń, jest dobrym pomysłem. Nie ma nic złego w zwykłej odpowiedzi na pytanie OP, nie muszę odrabiać za nich całej pracy domowej.
Soviut
1

Miałem ten sam problem podczas korzystania z funkcji poczty e-mail w języku Python. Poniżej znajduje się kod, który próbowałem pobrać temat wiadomości e-mail do zmiennej. Działa to dobrze w przypadku większości wiadomości e-mail i zapełniania zmiennej. Jeśli otrzymasz wiadomość e-mail z Yahoo lub podobnego, a nadawca nie wypełnił tematu, Yahoo nie utworzy tematu wiadomości e-mail, a funkcja zwróci wartość NoneType. Martineau udzielił poprawnej odpowiedzi, podobnie jak Soviut. Odpowiedź IMO Soviut jest bardziej zwięzła z punktu widzenia programowania; niekoniecznie z Pythona. Oto kod pokazujący technikę:

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
źródło
1

W niektórych sytuacjach pomocne jest posiadanie funkcji konwertującej None na int zero:

def nz(value):

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

    if value == None:
        return 0
    return value
user2920482
źródło