Как преобразовать Nonetype в int или string?

99

У меня есть Nonetypeзначение x, обычно это число, но может быть None. Я хочу разделить его на число, но Python поднимает:

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

Как я могу это решить?

user469652
источник
5
Предположим, что None эквивалентно 2771. Но, возможно, это не то, что вам нужно. Пожалуйста, дайте больше информации.
JoshD
Каким-то образом я получил значение Nonetype, оно должно было быть int, но теперь это объект Nonetype, и мне нужно разделить другое число, затем возникла ошибка.
user469652
int(None)выдает исключение, потому что None не может быть преобразовано в int. Ответ на ваш вопрос - это невозможно. Вы можете заменить что-нибудь, например 0, или 2771, или розового слона, но что бы вы ни заменили, вы все равно не сможете преобразовать None в int.
снимок
7
@ ma3204. преобразование Noneв розового слона тоже бесполезно, если только вы не работаете с какой-либо системой счисления, которая формально определяет деление числа розовым слоном (и вы написали код для его поддержки)
aaronasterling

Ответы:

50

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

Каким-то образом я получил значение 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 (см. Добрый ответ)
spider
1
@spider - это по-прежнему означает, что он сильно зависит от ситуации, и «определить разумную ценность» по-прежнему применяется.
Detly
Точка зрения паука вполне верна, этот ответ в основном просто говорит, что вы сделали что-то не так, но None не означает, что это означает неизвестное значение, которое может указывать на то, что вы сделали что-то не так, или, поскольку паук предложил отсутствующее значение, в общем случае должно быть 0 или, возможно, 1, для наиболее возможных вариантов использования None, где ожидается целое число.
Глен Флетчер
@glenflet Если вы не знаете, каков входной домен и спецификация вашей функции, посторонний в Интернете не сможет вам сказать. Если вы знаете, но не знаете синтаксис для его преобразования, это совершенно другой вопрос, чем заданный здесь.
Detly
318
int(value or 0)

Это будет использовать 0 в том случае, если вы предоставите любое значение, которое считает Python False, например None, 0, [], "" и т. Д. Поскольку 0 есть False, вы должны использовать только 0 в качестве альтернативного значения (в противном случае вы найдете свои 0s превращаясь в это значение).

int(0 if value is None else value)

Это заменяет только Noneна 0. Поскольку мы тестируем Noneспециально, вы можете использовать другое значение в качестве замены.

любезный
источник
65
user469652, вам следует подумать о том, чтобы сделать это принятым ответом. это на самом деле полезно, а не снисходительно
galarant
Я не уверен, решает ли это проблему, с которой сталкивается пользователь, т.е. используйте nonetype для выполнения вычислений ... в настоящее время я извлекаю данные через rest api, который возвращает nontype, содержащий числовое значение. Если я установлю его на 0 или оставлю как есть, я ничего не смогу с этим поделать
br3w5
2
Это, безусловно, лучший ответ, учитывая вопрос, поскольку пользователь указывает, что None, следует ожидать, как, возможно, функция, запрашивающая значение чего-то, возвращающего None, чтобы указать, что значение неизвестно, в этом случае None должно стать значением по умолчанию в его случае использования, который обычно равен 0. рассмотрите izip_longest, аргумент по умолчанию, если другой имеет другое значение по умолчанию (четный тип), тогда значение по умолчанию должно быть None, которое затем заменяется на значение по умолчанию, однако строка. <align_n> (str, w) принимает только целое число для ширины.
Глен Флетчер
2
Использовал это, и это было элегантно и решило мои проблемы.
Дэн Сэйф
1
мы можем использовать (value or 0)- без преобразования типа int - если мы уверены, что значение может быть только None или int
hashlash
17

Распространенный «питонический» способ справиться с подобной ситуацией известен как 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к подъему a , хотя, по общему признанию, это, вероятно, очень маловероятно. Тем не менее, я думаю, вы скажете, что в целом это хороший совет, которому нужно следовать.
Мартино 08
5

В Python 3 вы также можете использовать ключевое слово «или». Сюда:

foo = bar or 0
foo2 = bar or ""
Феррарези
источник
2

Я успешно использовал int (x или 0) для этого типа ошибки, пока None не должно равняться 0 в логике. Обратите внимание, что это также будет преобразовано в 0 в других случаях, когда проверка x возвращает False. например, пустой список, набор, словарь или строка нулевой длины. Извините, Киндалл уже дал этот ответ.

user3109122
источник
1

Это может произойти, если вы забудете вернуть значение из функции: тогда она вернет None. Посмотрите на все места, где вы назначаете эту переменную, и посмотрите, не является ли одно из них вызовом функции, в которой функция не имеет оператора возврата.

Йоуни К. Сеппянен
источник
1
... или функция имеет один или несколько операторов возврата, которые просто просты returnвместо return some_expression.
Джон Мачин,
... или функция содержит одно или несколько return Noneоператоров
Джон Мачин,
1

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

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

Примечание: my_value было намеренно установлено значение «Нет», чтобы доказать, что код работает и выполняется проверка.

Совиут
источник
1
вы должны использовать сравнение идентичности ( is [not] None)
shylent
-4 Вы должны поощрять ОП, чтобы он узнал, в чем его настоящая проблема, вместо того, чтобы избегать ее. Что сказал @shylent. Вы my_valueбезоговорочно устанавливаете значение None; Зачем? Вы не спрашиваете, почему ОП считает, что ему нужно что-то делать, int(my_value)когда my_value(если не Нет) «обычно число».
Джон Мачин,
1
Я установил my_value на None в качестве доказательства концепции, чтобы показать, что мой код не дает сбоев. Я не подвергал сомнению OP, потому что есть много причин, по которым значение не всегда может быть числом, и проверка его перед выполнением вычислений - хорошая идея. Нет ничего плохого в том, чтобы просто ответить на вопрос ОП, мне не нужно делать за них всю домашнюю работу.
Soviut
1

У меня была такая же проблема с использованием функций электронной почты Python. Ниже приведен код, который я пытался получить в переменной. Это отлично работает для большинства писем, и переменная заполняется. Если вы получили электронное письмо от Yahoo и т.п., и отправитель не заполнил строку темы, Yahoo не создает строку темы в электронном письме, и функция возвращает NoneType. Мартино дал правильный ответ так же, как и Совют. Ответ IMO Soviut более лаконичен с точки зрения программирования; не обязательно из 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 zero:

def nz(value):

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

    if value == None:
        return 0
    return value
user2920482
источник