it-roy-ru.com

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

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

4966
Devoted

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

a if condition else b

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

Это допускает короткое замыкание, потому что когда condition истинно, только a оценивается, а b вообще не оценивается, но когда condition ложно, только b оценивается, а a вообще не оценивается.

Например:

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

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

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

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


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

  • Порядок аргументов отличается от классического тернарного оператора condition ? a : b во многих других языках (таких как C, C++, Go, Perl, Ruby, Java, Javascript и т.д.), Что может привести к ошибкам, когда люди, не знакомые с Python «удивительное» поведение использует его (они могут изменить порядок аргументов).
  • Некоторые считают его «громоздким», поскольку он идет вразрез с нормальным потоком мыслей (сначала думая о состоянии, а затем о последствиях).
  • Стилистические причины.

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

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

5921
Vinko Vrsalovic

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

(falseValue, trueValue)[test]

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

(falseValue, trueValue)[test == True]

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

(falseValue, trueValue)[bool(<expression>)]
657
Landon Kuhn

Для версий до 2.5 есть хитрость:

[expression] and [on_true] or [on_false]

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

1. Есть ли эквивалент C '?: ”Троичный оператор?

271
James Brady

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
175
Simon Zimmermann

Из документации :

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

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

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

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

122
Michael Burr

Оператор для условного выражения в Python был добавлен в 2006 году как часть Python Enhancement 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]()

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

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

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 в Википедии

92
kenorb

@up:

К сожалению,

(falseValue, trueValue)[test]

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

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

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

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

Итак, история продолжается: выбор между 3 упомянутыми решениями - это компромисс между наличием функции короткого замыкания, использованием по крайней мере Python 2.5 (ИМХО больше не проблема) и отсутствием склонности к «trueValue-оценки-к-ложному» ошибки.

86
gorsky

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

[on_true] if [cond] else [on_false]

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

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

который может быть упакован:

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

и использовал этот способ:

q(cond, on_true, on_false)

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

54
Paolo

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

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

Вы можете часто находить

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
35
Benoit Bertholon

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

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
30
BattleDrum

Есть ли в 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 ожидает третьего выражения для else:

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

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

[expression1 for element in iterable if expression2]

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

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

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

expression1 if expression1 else expression2

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

expression1 or expression2

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

27
Aaron Hall

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

Например

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'
17
Sasikiran Vaddi

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

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

Пример:-

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

Это выведет «нечетное», если число нечетное, или «четное», если число четное.


Результат: - Если условие истинно, выполняется exp_1, иначе выполняется 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.

Точно так же в 

False and exp1 or exp2

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


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

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

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

15
Natesh bhat

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

Синтаксис:

[on_true] if [выражение] 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- Тернарный оператор может быть записан как вложенный if-else:

# 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
14
Ali Hallaji

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

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

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

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

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

12
Todor Minakov

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

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

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

10
Daniel Taub
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
10
ox.
a if condition else b

Просто запомните эту пирамиду, если у вас возникли проблемы с запоминанием:

     condition
  if           else
a                   b 
7
shivtej

ДА, у python есть троичный оператор, вот синтаксис и пример кода, чтобы продемонстрировать то же самое :)

#[On true] if [expression] else[On false]
# if the expression evaluates to true then it will pass On true otherwise On false


a= input("Enter the First Number ")
b= input("Enter the Second Number ")

print("A is Bigger") if a>b else print("B is Bigger")
6
PythonLover

Синтаксис: Тернарный оператор будет иметь вид:

[on_true] if [expression] else [on_false]

например

x, y = 25, 50
big = x if x < y else y
print(big)
4
Saurabh Chandra Patel

Да.

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

Многие языки программирования, полученные из C, обычно имеют следующий синтаксис тройного условного оператора:

<condition> ? <expression1> : <expression2>

Сначала PythonB enevolent D ictator F или L ife (я имею в виду Гвидо ван Россума, конечно ) отверг это (как непифонический стиль), так как это довольно трудно понять людям, не привыкшим к языку C. Кроме того, знак двоеточия : уже много раз используется в Python. После того, как PEP 308 был утвержден, Python наконец получил свое собственное условное выражение (что мы используем сейчас):

<expression1> if <condition> else <expression2>

Итак, во-первых, он оценивает состояние. Если он возвращает True, то будет вычисляться expression1 для получения результата, в противном случае будет оцениваться expression2. Из-за механики Lazy Evaluation - будет выполнено только одно выражение.

Вот несколько примеров (условия будут оцениваться слева направо):

pressure = 10
print('High' if pressure < 20 else 'Critical')

# Result is 'High'

Тернарные операторы могут быть соединены последовательно: 

pressure = 5
print('Normal' if pressure < 10 else 'High' if pressure < 20 else 'Critical')

# Result is 'Normal'

Следующий такой же, как предыдущий:

pressure = 5

if pressure < 20:
    if pressure < 10:
        print('Normal')
    else:
        print('High')
else:
    print('Critical')

# Result is 'Normal'

Надеюсь это поможет.

3
ARGeo

Оператор "условный". Тернар просто означает, что требуется три операнда. Мы не называем "бинарный" + оператор. Нет причин продолжать делать это с условным условием. Является ли это быстрее или более компактным, чем если-иначе, не имеет значения. Важно то, что это выражение, позволяющее встраивать его в другие выражения. При правильном использовании, это уменьшает избыточность и возможности для трудно различимых различий.

1
David McCracken

Одна из альтернатив условного выражения Python заключается в следующем:

{True:"yes", False:"no"}[boolean]

который имеет следующее расширение Nice:

{True:"yes", False:"no", None:"maybe"}[boolean_or_none]

Самая короткая альтернатива остается:

("no", "yes")[boolean]

но альтернативы нет, если вы хотите избежать оценки как yes(), так и no() в следующем:

yes() if [condition] else no()
1
Walter Tross

Да:

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

Х = 5, если что-то еще х = 10

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

1
Elad Goldenberg

если переменная определена, и вы хотите проверить, имеет ли она значение, вы можете просто 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
0
ewwink

Аккуратный способ связать несколько операторов:

f = lambda x,y: 'greater' if x > y else 'less' if y > x else 'equal'

array = [(0,0),(0,1),(1,0),(1,1)]

for a in array:
  x, y = a[0], a[1]
  print(f(x,y))

# Output is:
#   equal,
#   less,
#   greater,
#   equal

0
Yaakov Bressler