У Python есть тернарный условный оператор?



Answers

Вы можете индексировать в кортеж:

(falseValue, trueValue)[test]

test должен возвращать True или False .
Было бы безопаснее всегда выполнять его как:

(falseValue, trueValue)[test == True]

или вы можете использовать встроенный bool() для обеспечения Boolean значения:

(falseValue, trueValue)[bool(<expression>)]
Question

Если Python не имеет тернарного условного оператора, можно ли имитировать его с использованием других языковых конструкций?




Существует тройной вариант, как указано в других ответах, но вы также можете имитировать его с помощью «или», если вы проверяете значение boolean или None:

>>> a = False
>>> b = 5
>>> a or b
5

>>> a = None
>>> a or b
5



expression1 if условие else expression2

>>> a = 1
>>> b = 2
>>> 1 if a > b else -1 
-1
>>> 1 if a > b else -1 if a < b else 0
-1



У Python есть тернарный условный оператор?

Да. Из файла грамматики :

test: or_test ['if' or_test 'else' test] | lambdef

Интересующая часть:

or_test ['if' or_test 'else' test]

Итак, тернарная условная операция имеет вид:

expression1 if expression2 else expression3

expression3 будет оцениваться лениво (т.е. оцениваться только в том случае, если expression2 является ложным в булевом контексте). И из-за рекурсивного определения вы можете связать их бесконечно (хотя это может считаться плохим стилем).

expression1 if expression2 else expression3 if expression4 else expression5 # and so on

Примечание по использованию:

Обратите внимание, что каждый из них должен сопровождаться else . У людей, изучающих список понятий и выражений генератора, может показаться, что это трудный урок для изучения - следующее не будет работать, поскольку Python ожидает третьего выражения для другого:

[expression1 if expression2 for element in iterable]
#                          ^-- need an else here

который вызывает SyntaxError: invalid syntax . Таким образом, вышеперечисленное является либо неполной логикой (возможно, пользователь ожидает отсутствие-op в ложном состоянии), либо то, что может быть предназначено, - использовать выражение2 в качестве фильтра - отмечает, что следующим является законный Python:

[expression1 for element in iterable if expression2]

expression2 работает как фильтр для понимания списка и не является тернарным условным оператором.

Альтернативный синтаксис для более узкого случая:

Вам может показаться несколько болезненным написать следующее:

expression1 if expression1 else expression2

expression1 должно быть оценено дважды с вышеупомянутым использованием. Он может ограничить избыточность, если это просто локальная переменная. Тем не менее, общая и исполнительская питоновская идиома для этого случая использования заключается в использовании or сокращении поведения:

expression1 or expression2

что эквивалентно в семантике. Обратите внимание, что некоторые руководства по стилям могут ограничивать это использование на основе ясности - оно действительно придаёт большое значение очень малому синтаксису.




Для Python 2.5 и новее существует определенный синтаксис:

[on_true] if [cond] else [on_false]

В более старых Pythons тройной оператор не реализован, но его можно моделировать.

cond and on_true or on_false

Хотя есть потенциальная проблема, которая, если cond оценивает значение True а on_true - False , возвращается on_true вместо on_true . Если вы хотите, чтобы этот метод был в порядке, в противном случае используйте это:

{True: on_true, False: on_false}[cond is True] # is True, not == True

которые могут быть обернуты:

def q(cond, on_true, on_false)
    return {True: on_true, False: on_false}[cond is True]

и используется таким образом:

q(cond, on_true, on_false)

Он совместим со всеми версиями Python.




Больше подсказки, чем ответа (не нужно повторять очевидное для времени hundreth), но иногда я использую его как ярлык oneliner в таких конструкциях:

if conditionX:
    print('yes')
else:
    print('nah')

, становится:

print('yes') if conditionX else print('nah')

Некоторые (многие :) могут нахмуриться от него как беспартийного (даже рубино-иш :), но я лично считаю его более естественным, т. Е. Как вы его выражаете в обычном режиме, а также немного более визуально привлекательным в больших блоках кода.




Вы часто можете найти

cond and on_true or on_false

но это приводит к проблеме, когда on_true == 0

>>> x = 0
>>> print x == 0 and 0 or 1 
1
>>> x = 1
>>> print x == 0 and 0 or 1 
1

где вы ожидаете, что для нормального тернарного оператора этот результат

>>> x = 0
>>> print 0 if x == 0 else 1 
0
>>> x = 1
>>> print 0 if x == 0 else 1 
1



Да.

>>> b = (True if 5 > 4 else False)
>>> print b
True



Оператор условного выражения в Python был добавлен в 2006 году как часть Python Enhancement Proposal 308 . Его форма отличается от обычного ?: Оператор и это:

<expression1> if <condition> else <expression2>

что эквивалентно:

if <condition>: <expression1> else: <expression2>

Вот пример:

result = x if a > b else y

Другой синтаксис, который можно использовать (совместимый с версиями до 2.5):

result = (lambda:y, lambda:x)[a > b]()

где операнды оцениваются лениво .

Другой способ - индексирование кортежа (что не согласуется с условным оператором большинства других языков):

result = (y, x)[a > b]

или явно построенный словарь:

result = {True: x, False: y}[a > b]

Другой (менее надежный), но более простой способ - использовать и / or операторы:

result = (a > b) and x or y

однако это не сработает, если x будет False .

Возможным обходным путем является создание списков x или y или кортежей, как показано ниже:

result = ((a > b) and [x] or [y])[0]

или:

result = ((a > b) and (x,) or (y,))[0]

Если вы работаете со словарями, вместо использования тернарного условного кода вы можете воспользоваться get(key, default) , например:

shell = os.environ.get('SHELL', "/bin/sh")

Источник: ?:




In [1]: a = 1 if False else 0

In [2]: a
Out[2]: 0

In [3]: b = 1 if True else 0

In [4]: b
Out[4]: 1





Links