Як перетворити Nonetype на int або string?


96

У мене є Nonetypeзначення x, це, як правило, число, але може бути None. Я хочу розділити його на число, але Python піднімає:

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

Як я можу це вирішити?


5
Припустимо, що None еквівалентно 2771. Але, можливо, це не те, що ви хочете. Будь ласка, надайте більше інформації.
JoshD

Якось я отримав значення Nonetype, це повинно було бути int, але це тепер об'єкт Nonetype, і мені потрібно розділити інше число, тоді помилка виникла.
user469652

int(None)видає виняток, оскільки None неможливо перетворити на int. Відповідь на ваше запитання - це неможливо зробити. Ви можете замінити щось, наприклад 0, або 2771, або рожевого слона, але все, що ви заміните, ви все одно не зможете перетворити None на int.
snapshoe

7
@ ma3204. перетворення Noneна рожевого слона теж не годиться, якщо ви не працюєте з якоюсь числовою системою, яка формально визначає ділення числа на рожевого слона (і ви написали код для його резервного копіювання)
aaronasterling

Відповіді:


49

В одному з коментарів ви говорите:

Якось я отримав значення Nonetype, це повинно було бути int, але зараз це об’єкт Nonetype

Якщо це ваш код, з’ясуйте, як ви переживаєте, Noneколи очікуєте число, і зупиніть це .

Якщо це чужий код, з’ясуйте умови, за яких він Noneвидається, і визначте розумне значення, яке потрібно використовувати для цього, за допомогою звичайного умовного коду:

result = could_return_none(x)

if result is None:
    result = DEFAULT_VALUE

...або навіть...

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.

Немає жодної причини для автоматичного використання 0тут - рішень, які залежать від "хибності"None припущення, що ви захочете цього. DEFAULT_VALUE(Якщо вона взагалі існує) повністю залежить від мети вашого коду.


5
+1 за "правильне" рішення. Якщо ваше вікно часто таємниче ламається, з’ясуйте, чому (і

3
Це не корисно, якщо ви отримуєте ключі зі словника redis, наприклад, оскільки відсутні ключі будуть None. Якщо ви хочете підсумувати їх незалежно від їх присутності (що є цілком прийнятною поведінкою), можливо, вам доведеться перевести None в 0 (див. Відповідь kindall)
павук

1
@spider - це все ще означає, що він сильно залежить від ситуації, і "визначення розумної цінності" все ще застосовується.
помер

Точка павука цілком вірна. Ця відповідь в основному просто говорить, що ви зробили щось не так, але None не означає, що це означає невідоме значення, яке може свідчити про те, що ви зробили щось неправильно, або як павук запропонував відсутність значення, загалом воно повинно прийти 0 або, можливо, 1, для більшості можливих застосувань None, де очікується ціле число.
Глен Флетчер,

@glenflet Якщо ви не знаєте, що таке вхідний домен і специфікація вашої функції, незнайомець в Інтернеті не зможе вам сказати. Якщо ви знаєте, але не знаєте синтаксису для його перетворення, це вже зовсім інше питання, ніж те, що задано тут.
detly

312
int(value or 0)

Це буде використовувати 0 у випадку, коли ви надаєте будь-яке значення, яке вважає Python False, наприклад None, 0, [], "" і т. Д. Оскільки 0 є False, ви повинні використовувати лише 0 як альтернативне значення (інакше ви знайдете свої 0 перетворюючись на це значення).

int(0 if value is None else value)

Це замінює лише Noneна 0. Оскільки ми тестуємо Noneспеціально, ви можете використовувати якесь інше значення як заміну.


64
user469652, замість цього вам слід розглянути можливість прийняти цю відповідь. це насправді корисно на відміну від поблажливого
галарант

я не впевнений, чи вирішує це проблему, з якою стикається користувач, тобто. використовуйте nonetype для виконання обчислення ... я зараз витягую дані через api rest, який повертає nonetype, що містить числове значення. Якщо я
ставлю

2
Це зухвало найкраща відповідь, враховуючи питання, оскільки користувач вказує, що None, слід очікувати, як, можливо, функція, що вимагає значення чогось, що повертається None, щоб вказати значення невідоме, у цьому випадку None має стати значенням за замовчуванням у випадку використання, яке зазвичай дорівнює 0. розглянемо аргумент izip_longest, аргумент за замовчуванням, для іншого він має інший тип за замовчуванням (навіть тип), тоді значенням за замовчуванням має бути None, яке потім замінюється на значення за замовчуванням, однак рядок. <align_n> (str, w) приймає ціле число лише для ширини.
Глен Флетчер,

2
Використовував це, і це було елегантно і вирішувало мої проблеми.
Dan Safee

1
ми можемо використовувати (value or 0)- без лиття типу int - якщо ми запевнили, що значенням може бути лише None або int
хеш-хеш

16

Поширений "пітонічний" спосіб вирішення подібної ситуації відомий як EAFP, оскільки " простіше просити прощення, ніж дозволу ". Що зазвичай означає написання коду, який передбачає, що все в порядку, але потім обгортання його символомtry..except блоком на випадок, щоб обробляти речі, коли цього немає.

Ось такий стиль кодування застосовується до вашої проблеми:

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

answer = my_value / divisor

Або, можливо, ще простіший і трохи швидший:

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

Зворотний і більш традиційний підхід відомий як LBYL, що означає " Подивіться, перш ніж стрибати " - це те, що пропонують @Soviut та деякі інші. Для додаткового висвітлення цієї теми див. Мою відповідь та відповідні коментарі до питання Визначте, чи присутній ключ у словнику в іншому місці на цьому сайті.

Однією з потенційних проблем EAFP є те, що він може приховати той факт, що щось не так з якоюсь іншою частиною коду або стороннім модулем, який ви використовуєте, особливо коли винятки часто трапляються (і тому насправді не є "винятковими" випадками зовсім).


11

Це TypeErrorз’являється лише при спробі пройти int() None(що є єдиним NoneTypeзначенням, наскільки мені відомо). Я б сказав, що вашою справжньою метою не повинно бути перетворення NoneTypeна intабо str, а з’ясування, куди / чому ви отримуєте Noneзамість числа, як очікувалося, або виправити це, або обробити Noneналежним чином.


Передача int()складного числа, наприклад int(1+2j), також призведе TypeErrorдо підвищення а, хоча, правда, це, мабуть, дуже малоймовірно. Незважаючи на це, я вважаю, що ви, без сумніву, були б, загалом, гарною порадою для дотримання.
martineau

5

У Python 3 ви також можете використовувати ключове слово "або". Сюди:

foo = bar or 0
foo2 = bar or ""

2

Я успішно використовував int (x або 0) для цього типу помилок, доки None не повинен дорівнювати 0 в логіці. Зверніть увагу, що це також призведе до 0 в інших випадках, коли тестування x повертає False. наприклад, порожній список, набір, словник або рядок нульової довжини. Вибачте, Кіндалл вже дав цю відповідь.


1

Це може статися, якщо ви забудете повернути значення з функції: тоді вона повертає None. Подивіться на всі місця, де ви призначаєте цю змінну, і переконайтеся, що одним із них є виклик функції, де у функції відсутній оператор return.


1
... або функція має одне або декілька операторів повернення, які просто returnзамість return some_expression.
John Machin

... або функція містить одне або декілька return Noneтверджень
Джон Махін,

1

Вам слід перевірити, щоб переконатися, що значення не є None, перш ніж намагатися виконати будь-які обчислення за ним:

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

Примітка: my_value було навмисно встановлено значення None для підтвердження роботи коду та перевірки.


1
вам слід скористатися порівнянням особи ( is [not] None)
shylent

-4 Ви повинні заохочувати ОП з’ясувати, в чому полягає його справжня проблема, замість того, щоб уникати її. Що сказав @shylent. Ви my_valueбеззастережно встановили значення Ні; чому? Ви не ставите під сумнів, чому ОП вважає, що йому потрібно робити, int(my_value)коли my_valueце (якщо не Жодне) "загалом число".
John Machin

1
Я встановив для my_value значення None як доказ концепції, щоб показати, що мій код не провалюється. Я не ставив під сумнів OP, оскільки є багато причин, чому значення не завжди може бути числом, і перевірка того, чи є воно перед виконанням обчислень, є гарною ідеєю. Немає нічого поганого в тому, щоб просто відповісти на запитання ОП, мені не потрібно робити за них усі домашні завдання.
Soviut

1

У мене була та ж проблема з використанням функцій електронної пошти python. Нижче наведено код, який я намагався отримати тему електронної пошти у змінну. Це чудово працює для більшості електронних листів та заповнення змінної. Якщо ви отримуєте електронне повідомлення від Yahoo або подібного, а відправник не заповнював рядок теми, Yahoo не створює рядок теми в електронному листі, і ви отримуєте функцію NoneType. Мартіно дав правильну відповідь так само, як і Совіт. Відповідь ІМО Равіут є більш стислою з точки зору програмування; не обов’язково з Python. Ось декілька кодів, щоб показати техніку:

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()

1

У деяких ситуаціях корисно мати функцію перетворення None в int нуль:

def nz(value):

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

    if value == None:
        return 0
    return value
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.