Имеет ли Python троичный условный оператор?

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

23 ответов


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

a if condition else b

первый condition оценивается, то либо a или b возвращается на основе Boolean стоимостью condition
Если condition значение правда a возвращается, еще b возвращается.

например:

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

обратите внимание, что условия являются выражение, не a сообщении. Это означает, что вы не можете использовать назначения или pass или другие утверждения в условном:

>>> pass if False else x = 3
  File "<stdin>", line 1
    pass if False else x = 3
          ^
SyntaxError: invalid syntax

в таком случае, вы должны использовать обычный if оператор вместо условного.


имейте в виду, что это не одобряется некоторыми Pythonistas по нескольким причинам:

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

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

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


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

(falseValue, trueValue)[test]

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

(falseValue, trueValue)[test == True]

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

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

для версий до 2.5 есть трюк:

[expression] and [on_true] or [on_false]

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

1. есть ли эквивалент C "?:" тернарный оператор?


expression1 Если условие другое 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.

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

посмотреть PEP 308 для получения дополнительной информации об условных выражениях.

New начиная с версии 2.5.


оператор условного выражения в Python был добавлен в 2006 году как часть Предложение По Улучшению Python 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 в Википедии


@up:

к сожалению,

(falseValue, trueValue)[test]

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

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

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

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

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


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

[on_true] if [cond] else [on_false]

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

cond and on_true or on_false

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

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

который можно обернуть by:

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

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

q(cond, on_true, on_false)

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


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

здесь я просто пытаюсь показать некоторые важные различия в 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

тернарный оператор в Скала!--15-->

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. свой высоки читаемый и ремонтопригодный.


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

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

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

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

имеет ли Python троичный условный оператор?

да. От грамматика:

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

часть интереса:

or_test ['if' or_test 'else' test]

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

expression1 if expression2 else expression3

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

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

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

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

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

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

[expression1 for element in iterable if expression2]

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

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

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

expression1 if expression1 else expression2

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

expression1 or expression2

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


моделирование троичного оператора 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'

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

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

пример:

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

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


результат :- если условие true, exp_1 выполняется, иначе exp_2 выполняется.

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

вот как это работает:

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

0 and exp

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

на

1 or exp

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

но в случае

True and exp1 or exp2

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

аналогично

False and exp1 or exp2

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


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

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

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


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

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

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

, будет:

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

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


троичный условный оператор просто позволяет тестировать условие в одной строке, заменяя многострочный if-else, делая код компактным.

синтаксис :

[on_true] if [expression] else [on_false]

1-Простой метод использования троичного оператора:

# Program to demonstrate conditional operator
a, b = 10, 20
# Copy value of a in min if a < b else copy b
min = a if a < b else b
print(min)  # Output: 10

2-прямой метод использования кортежей, словаря и лямбды:

# Python program to demonstrate ternary operator
a, b = 10, 20
# Use tuple for selecting an item
print( (b, a) [a < b] )
# Use Dictionary for selecting an item
print({True: a, False: b} [a < b])
# lamda is more efficient than above two methods
# because in lambda  we are assure that
# only one expression will be evaluated unlike in
# tuple and Dictionary
print((lambda: b, lambda: a)[a < b]()) # in output you should see three 10

3 - тернарный оператор может быть записан как вложенный если-то:

# Python program to demonstrate nested ternary operator
a, b = 10, 20
print ("Both a and b are equal" if a == b else "a is greater than b"
        if a > b else "b is greater than a")

выше подход можно записать как:

# Python program to demonstrate nested ternary operator
a, b = 10, 20
if a != b:
    if a > b:
        print("a is greater than b")
    else:
        print("b is greater than a")
else:
    print("Both a and b are equal") 
# Output: b is greater than a

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

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

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


да.

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

да:

предположим, вы хотите дать переменной x некоторое значение, если какой-то bool истинен и аналогично

X = 5, если что-то еще x = 10

X = [некоторое значение] если [если это верно, первое значение оценивает] другое [другое значение оценивает]


синтаксис: Тернарный оператор будет задан как:

[on_true] if [expression] else [on_false]

Эл.г

x, y = 25, 50
big = x if x < y else y
print(big)

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

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

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

если переменная определена и вы хотите проверить, если это имеет значение, вы можете просто a or b

def test(myvar=None):
    # shorter than: print myvar if myvar else "no Input"
    print myvar or "no Input"

test()
test([])
test(False)
test('hello')
test(['Hello'])
test(True)

выводит

no Input
no Input
no Input
hello
['Hello']
True