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

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

3705
задан Devoted 27 дек. '08 в 11:32
источник поделиться

19 ответов

Да, это было добавлено в версии 2.5.
Синтаксис:

a if condition else b

Сначала оценивается condition, затем возвращается a или b на основе Boolean значение condition
Если condition получает значение True, возвращается a, возвращается b.

Например:

>>> 'true' if True else 'false'
'true'
>>> 'true' if False else 'false'
'false'

Имейте в виду, что некоторые из Pythonistas на него нахмурились по нескольким причинам:

  • Порядок аргументов отличается от многих других языков (таких как C, Ruby, Java и т.д.), что может привести к ошибкам, когда люди, незнакомые с "удивительным" поведением Python, используют его (они могут изменить порядок).
  • Некоторые считают его "громоздким", поскольку он противоречит нормальному потоку мысли (сначала думая о состоянии, а затем о последствиях).
  • Стилистические причины.

Если у вас возникли проблемы с запоминанием порядка, помните, что если вы прочитаете его вслух, вы (почти) скажете, что вы имеете в виду. Например, x = 4 if b > 8 else 9 читается вслух как x will be 4 if b is greater than 8 otherwise 9.

Официальная документация:

4400
ответ дан Vinko Vrsalovic 27 дек. '08 в 11:44
источник поделиться

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

(falseValue, trueValue)[test]

test необходимо вернуть True или False.
Возможно, было бы безопаснее всегда выполнять его как:

(falseValue, trueValue)[test == True]

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

(falseValue, trueValue)[bool(<expression>)]
503
ответ дан Landon Kuhn 22 янв. '09 в 21:58
источник поделиться

Для версий до 2.5 существует трюк:

[expression] and [on_true] or [on_false]

Он может давать неправильные результаты, когда on_true  имеет ложное логическое значение. 1
Хотя это имеет смысл оценить выражения слева направо, что яснее, на мой взгляд.

<суб > 1. Есть ли эквивалент Cs "?:" трехмерный оператор?

205
ответ дан James Brady 27 дек. '08 в 13:48
источник поделиться

выражение1, если условие 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
123
ответ дан Simon Zimmermann 27 мая '10 в 10:56
источник поделиться

От документация:

Условные выражения (иногда называемые "тройным оператором" ) имеют самый низкий приоритет всех операций Python.

Выражение x if C else y сначала оценивает условие, C (не x); если C истинно, x оценивается и возвращается его значение; в противном случае y вычисляется и возвращается его значение.

Подробнее о условных выражениях см. PEP 308.

Новый с версии 2.5.

89
ответ дан Michael Burr 27 дек. '08 в 11:44
источник поделиться

Оператор условного выражения в 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]

Другой (менее надежный), но более простой метод - использовать операторы and и 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")

Источник: ?: в Python в Википедии

60
ответ дан kenorb 05 мая '15 в 15:00
источник поделиться

@up:

К сожалению,

(falseValue, trueValue)[test]
Решение

не имеет поведения короткого замыкания; таким образом, как falseValue, так и trueValue оцениваются независимо от условия. Это может быть субоптимально или даже ошибочно (т.е. Как trueValue, так и falseValue могут быть методами и иметь побочные эффекты).

Одним из решений этого было бы

(lambda: falseValue, lambda: trueValue)[test]()

(выполнение задерживается до тех пор, пока не будет известен победитель;)), но он вводит несогласованность между вызываемыми и не вызываемыми вызовами объектами. Кроме того, он не решает проблему при использовании свойств.

Итак, история - выбор между тремя упомянутыми решениями - это компромисс между наличием функции короткого замыкания с использованием, по крайней мере, python 2.5 (IMHO больше не проблема) и не подвержен "trueValue-оценке-to -false".

56
ответ дан gorsky 06 дек. '09 в 14:51
источник поделиться

Для 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_false. Если вы хотите, чтобы этот метод был в порядке, в противном случае используйте это:

{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.

40
ответ дан Paolo 25 апр. '12 в 14:40
источник поделиться

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

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
27
ответ дан Benoit Bertholon 14 янв. '13 в 18:56
источник поделиться

Тернарный оператор в разных языках программирования

Здесь я просто попытаюсь показать некоторую важную разницу в ternary operator между двумя языками программирования.

Тернарный оператор в Javascript

var a = true ? 1 : 0;
# 1
var b = false ? 1 : 0;
# 0

Тернарный оператор в Ruby

a = true ? 1 : 0
# 1
b = false ? 1 : 0
# 0

Тернарный оператор в Scala

val a = true ? 1 | 0
# 1
val b = false ? 1 | 0
# 0

Тернарный оператор в программировании R

a <- if (TRUE) 1 else 0
# 1
b <- if (FALSE) 1 else 0
# 0

Тернарный оператор в Python

a = 1 if True else 0
# 1
b = 1 if False else 0
# 0

Теперь вы можете увидеть красоту языка python. его читабельность и удобство обслуживания.

25
ответ дан Simplans 21 авг. '16 в 20:56
источник поделиться

Абсолютно, и это невероятно легко понять.

general syntax : first_expression if bool_expression_is_true else second_expression

Example: x= 3 if 3 > 2 else 4 
# assigns 3 to x if the boolean expression evaluates to true or 4 if it is false
23
ответ дан BattleDrum 15 июля '15 в 14:33
источник поделиться

У 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

Замечание об использовании:

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

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

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

[expression1 for element in iterable if expression2]

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

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

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

expression1 if expression1 else expression2

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

expression1 or expression2

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

18
ответ дан Aaron Hall 17 нояб. '15 в 22:14
источник поделиться

Имитация троичного оператора python.

Например

a, b, x, y = 1, 2, 'a greather than b', 'b greater than a'
result = (lambda:y, lambda:x)[a > b]()

выход:

'b greater than a'
12
ответ дан Sasikiran Vaddi 20 нояб. '13 в 13:44
источник поделиться
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
6
ответ дан ox. 07 мая '14 в 16:02
источник поделиться

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

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

становится:

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

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

5
ответ дан Todor 11 мая '16 в 10:13
источник поделиться

Да, вы можете использовать его таким образом:

is_fat = True
state = "fat" if is_fat else "not fat"

Подробнее о тернарный условный оператор

4
ответ дан Daniel Taub 10 июня '17 в 16:14
источник поделиться

вы можете сделать это: -

[condition] and [expression_1] or [expression_2] ;

Пример: -

print(number%2 and "odd" or "even")

Это будет печатать "нечетные", если число нечетное или "четное", если число четное.


Результат: - Если условие истинно, exp_1 выполняется else выполняется exp_2.

Примечание: - 0, None, False, emptylist, emptyString оценивается как False. И любые данные, кроме 0, имеют значение True.

Здесь как это работает:

если условие [условие] становится "истинным", тогда выражение_1 будет оцениваться, но не выражение_2. Если мы "и" что-то с 0 (ноль), результат всегда будет неустойчивым. Итак, в приведенном ниже выражении

0 and exp

Выражение exp не будет вообще оцениваться, так как "и" с 0 всегда будут оцениваться до нуля и нет необходимости оценивать выражение. Вот как работает сам компилятор на всех языках.

В

1 or exp

выражение exp не будет вообще оцениваться, так как "или" с 1 всегда будет 1. Поэтому он не будет оценивать выражение exp, так как результат будет равен 1. (методы оптимизации компилятора).

Но в случае

True and exp1 or exp2

Второе выражение exp2 не будет оцениваться, так как True and exp1 будет True, если exp1 не является ложным.

Аналогично в

False and exp1 or exp2

Выражение exp1 не будет оцениваться, так как False эквивалентно записи 0, а "и" с 0 будет 0, но после exp1, поскольку используется "или" , он будет оценивать выражение exp2 после "или" .


Примечание: - Этот вид ветвления с использованием "или" и "и" может использоваться только тогда, когда выражение_1 не имеет значения правды False (или 0 или None или emptylist []] или emptystring ''.), так как если выражение_1 становится False, то выражение_2 будет оцениваться из-за наличия "или" между exp_1 и exp_2.

Если вы все еще хотите заставить его работать во всех случаях, независимо от того, что истинны значения exp_1 и exp_2, сделайте следующее: -

[condition] and ([expression_1] or 1) or [expression_2] ;

3
ответ дан Natesh bhat 20 авг. '17 в 10:31
источник поделиться

Да.

>>> b = (True if 5 > 4 else False)
>>> print b
True
2
ответ дан Alejandro Blasco 16 марта '16 в 19:36
источник поделиться

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

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

>>> a = None
>>> a or b
5
-2
ответ дан Meow 08 дек. '16 в 22:05
источник поделиться

Другие вопросы по меткам