В C # есть оператор слияния нуля (записанный как ??
), который позволяет легко (коротко) проверять нуль во время присваивания:
string s = null;
var other = s ?? "some default value";
Есть ли эквивалент в Python?
Я знаю, что я могу сделать:
s = None
other = s if s else "some default value"
Но есть ли еще более короткий путь (где мне не нужно повторяться s
)?
python
null-coalescing-operator
Клаус Бысков Педерсен
источник
источник
??
Оператор предлагается в качестве PEP 505 .Ответы:
Хорошо, нужно уточнить, как
or
работает оператор. Это логический оператор, поэтому он работает в логическом контексте. Если значения не являются логическими, они преобразуются в логические для целей оператора.Обратите внимание, что
or
оператор не возвращает толькоTrue
илиFalse
. Вместо этого он возвращает первый операнд, если первый операнд оценивается как true, и возвращает второй операнд, если первый операнд оценивается как false.В этом случае выражение
x or y
возвращается,x
если оно равноTrue
или оценивается как истинное при преобразовании в логическое значение. В противном случае он возвращаетсяy
. В большинстве случаев это будет служить той же цели, что и оператор C♯ с нулевым слиянием, но имейте ввиду:Если вы используете свою переменную
s
для хранения чего-либо, что является либо ссылкой на экземпляр класса, либоNone
(если ваш класс не определяет членов__nonzero__()
и__len__()
), можно безопасно использовать ту же семантику, что и оператор слияния нулей.На самом деле, может быть даже полезно иметь этот побочный эффект Python. Поскольку вы знаете, какие значения оцениваются как ложные, вы можете использовать это для запуска значения по умолчанию, не используя
None
специально (например, объект ошибки).В некоторых языках это поведение называется оператором Элвиса .
источник
s
это допустимое значение, но не правдивое? (Я не знаю Python, поэтому я не уверен, применима ли концепция «правдивого».)None
и пустые контейнеры (включая строки) считаются ложными, в дополнение к константеFalse
. Большинство всего остального считается правдой. Я бы сказал, что главной опасностью здесь будет то, что вы получите истинное, но не строковое значение, но это не будет проблемой в некоторых программах.datetime.time(0)
тоже был фальшивый!Строго,
Иначе
s = False
станет"default value"
, что может не соответствовать тому, что было задумано.Если вы хотите сделать это короче, попробуйте:
источник
Consider x()?.y()?.z()
Вот функция, которая будет возвращать первый аргумент, который не является
None
:reduce()
может излишне перебирать все аргументы, даже если первый аргумент неNone
, поэтому вы также можете использовать эту версию:источник
def coalesce(*arg): return next((a for a in arg if a is not None), None)
делает так же, как ваш последний пример в одной строке.Consider x()?.y()?.z()
Я понимаю, что это ответ, но есть другой вариант, когда вы имеете дело с объектами.
Если у вас есть объект, который может быть:
Ты можешь использовать:
Подобно:
При добавлении
{}
в качестве значения по умолчанию, если «имя» отсутствует, пустой объект возвращается и передается следующему get. Это похоже на null-safe-navigation в C #, что было бы похожеobj?.name?.first
.источник
.get
, это работает только для объектов,getattr()
также.get
on dict не использует параметр по умолчанию, если значение равно None, но использует параметр по умолчанию, если значение не существует, поскольку ключ отсутствует в dict.{'a': None}.get('a', 'I do not want None')
все равно даст вамNone
в результате.В дополнение к ответу Джулиано о поведении «или»: это «быстро»
Так что иногда это может быть полезным ярлыком для таких вещей, как
источник
В дополнение к ответу @Bothwells (который я предпочитаю) для отдельных значений, для проверки нулевых значений, возвращаемых функцией, вы можете использовать новый оператор walrus (начиная с python3.8):
Таким образом,
test
функцию не нужно оценивать два раза (как вa = 2 if test() is None else test()
)источник
В случае, если вам нужно вложить более одной операции объединения, например:
model?.data()?.first()
Это не легко решаемая проблема
or
. Это также не может быть решено, для.get()
которого требуется тип словаря или аналог (и не может быть вложен в любом случае) илиgetattr()
который вызовет исключение, когда NoneType не имеет атрибута.Соответствующий пункт, рассматривающий добавление нулевого слияния в язык, - это PEP 505, и обсуждение, относящееся к документу, находится в ветке идей python .
источник
Что касается ответов @Hugh Bothwell, @mortehu и @glglgl.
Настройка набора данных для тестирования
Определить реализации
Сделать тестовую функцию
Результаты на Mac i7 @ 2,7 ГГц с использованием Python 2,7
Очевидно, что
not_none
функция отвечает на вопрос ОП правильно и обрабатывает проблему «ложных». Это также самый быстрый и легкий для чтения. Если применять логику во многих местах, это явно лучший путь.Если у вас есть проблема, когда вы хотите найти 1-е ненулевое значение в итерируемом, то ответ @ mortehu - это путь. Но это решение другой проблемы, нежели OP, хотя он может частично справиться с этим делом. Он не может принимать итерируемое И значение по умолчанию. Последним аргументом будет возвращаемое значение по умолчанию, но тогда в этом случае вы не передадите итерируемое, так как не очевидно, что последний аргумент является значением по умолчанию.
Затем вы могли бы сделать это ниже, но я бы все еще использовал
not_null
для варианта использования одно значение.источник
Для таких, как я, которые наткнулись здесь на поиски жизнеспособного решения этой проблемы, когда переменная может быть неопределенной, самое близкое, что я получил, это:
Обратите внимание, что при проверке глобальных переменных требуется строка, но впоследствии при проверке значения используется фактическая переменная.
Подробнее о существовании переменных: как проверить, существует ли переменная?
источник
(variablename or False) == True
так же, какvariablename == True
если вы не можете найти имя внутри словаря, он вернет значение по умолчанию, если имя существует, то будет добавлено любое существующее значение с 1.
надеюсь, это поможет
источник
Две нижеприведенные функции оказались очень полезными при работе со многими переменными вариантами тестирования.
источник