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

6051

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

посвятили
источник
149
В официальной документации Python 3.0, на которую есть ссылка в комментарии выше, это называется «условные выражения» и очень загадочно определено. Эта документация даже не включает термин «троичный», поэтому вам будет сложно найти его через Google, если вы точно не знаете, что искать. Документация версии 2 несколько более полезна и содержит ссылку на «PEP 308» , которая включает в себя много интересного исторического контекста, связанного с этим вопросом.
Нобар
26
«троичный» (имеющий три входа) является косвенным свойством этого побуждения, а не определяющим свойством концепции. Например: SQL имеет case [...] { when ... then ...} [ else ... ] endаналогичный эффект, но никак не троичный.
user313114 15.12.14
10
также раздел 6.5.15 ИСО / МЭК 9899 (стандарт языка программирования C) называет его «условным оператором»
user313114
9
Википедия подробно описывает это в статье " ?: ".
Привет, до свидания,
9
За годы, прошедшие после комментария nobar, документация по условным выражениям была обновлена ​​и теперь содержит условные выражения (иногда называемые «троичным оператором») ...
Скотт Мартин,

Ответы:

7048

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

a if condition else b

Сначала conditionоценивается, затем точно один из aили bоценивается и возвращается на основе логического значения 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

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

x = a if True else b

Думайте об условном выражении как о переключении между двумя значениями. Это очень полезно, когда вы находитесь в ситуации «одного значения или другого», но больше ничего не делает.

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


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

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

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

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

Винко Врсалович
источник
270
Порядок может показаться странным для программистов, однако f(x) = |x| = x if x > 0 else -xдля математиков это звучит очень естественно. Вы также можете понять это, как и A в большинстве случаев, за исключением случаев, когда C, тогда вы должны вместо этого делать B ...
yota
122
Будьте осторожны с порядком операций при использовании этого. Например, линия z = 3 + x if x < y else y. Если x=2и y=1, вы можете ожидать, что это даст 4, но это на самом деле приведет к 1. z = 3 + (x if x > y else y)это правильное использование.
Кэл Зекдор
11
Смысл был в том, что если вы хотите выполнить дополнительные вычисления после вычисления условного выражения, например добавить значение к результату, вам нужно либо добавить дополнительное выражение в обе стороны ( z = 3 + x if x < y else 3 + y), либо сгруппировать условное выражение ( z = 3 + (x if x < y else y)или z = (x if x < y else y) + 3)
Kal Zekdor
4
@MrGeek, я понимаю, что вы имеете в виду, так что вы будете в основном вкладывать операции: `" foo ", если Bool else (" bar ", если Bool else" foobar ")`
Dimesio
3
Программисты нуждаются в точной правильной формулировке даже больше, чем математик, потому что в математике всегда есть прибегание к базовым понятиям. Убедительным аргументом является оператор%, имитирующий то, как «мод» используется в математике, был бы катастрофой. Так что нет, я не принимаю ваш аргумент. Это как придерживаться имперских единиц. Groetjes Альберт
Альберт ван дер Хорст
801

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

(falseValue, trueValue)[test]

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

(falseValue, trueValue)[test == True]

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

(falseValue, trueValue)[bool(<expression>)]
Лэндон Кун
источник
591
Обратите внимание, что этот всегда оценивает все, тогда как конструкция if / else оценивает только выигрышное выражение.
SilverbackNet
117
(lambda: print("a"), lambda: print("b"))[test==true]()
Дастин Гетц
15
Следует отметить, что то, что находится внутри []s, может быть произвольным выражением. Кроме того, для безопасности вы можете явно проверить на правдивость, написав [bool(<expression>)]. Эта bool()функция существует с v2.2.1.
Мартино
12
Я проделал подобный трюк - только один или два раза, но сделал это - путем индексации в словаре с ключами Trueи Falseв качестве ключей: {True:trueValue, False:falseValue}[test] я не знаю, является ли это менее эффективным, но он, по крайней мере, избегает всего «элегантный» против «некрасивых» дебатов. Там нет двусмысленности, что вы имеете дело с логическим, а не с Int.
JDM
339

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

[expression] and [on_true] or [on_false]

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

1. Есть ли эквивалент троичного оператора C?

Джеймс Брейди
источник
67
Для этого нужно использовать (test and [true_value] или [false_value]) [0], что позволяет избежать этой ловушки.
ThomasH
6
Троичный оператор обычно выполняется быстрее (иногда на 10-25%).
вулкан
7
@ Volcano У тебя есть источник для меня?
OrangeTux,
4
@OrangeTux Вот разобранный код . Использование метода, предложенного ThomasH, будет еще медленнее.
mbomb007
266

<expression 1> if <condition> else <expression 2>

a = 1
b = 2

1 if a > b else -1 
# Output is -1

1 if a > b else -1 if a < b else 0
# Output is -1
Simon Zimmermann
источник
83
Этот подчеркивает основной смысл троичного оператора: выбор значения. Это также показывает, что более одного троичного можно объединить в одно выражение.
Рой Тинкер
6
@ Крейг, я согласен, но также полезно знать, что произойдет, когда нет скобок. В реальном коде я тоже склонен вставлять явные скобки.
Джон Кумбс
160

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

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

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

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

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

Майкл Берр
источник
121

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

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

kenorb
источник
1
result = {1: x, 0: y}[a > b]другой возможный вариант ( Trueи Falseна самом деле целые числа со значениями 1и 0)
Уолтер Тросс
99

К сожалению,

(falseValue, trueValue)[test]

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

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

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

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

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

gorsky
источник
2
Хотя кортеж лямбда-трюка работает, он занимает примерно 3 раза дольше, чем троичный оператор. Вероятно, будет разумной идеей, если она сможет заменить длинную цепочку if else if.
Перкинс
72

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

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

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

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

Троичный оператор в рубине

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

Тернарный оператор в Скале

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
Simplans
источник
5
Это может звучать самоуверенно; но в сущности это говорит о том, что синтаксис Python, вероятно, будет понят человеком, который никогда не видел троичного оператора, в то время как очень немногие люди поймут более обычный синтаксис, если им сначала не скажут, что он означает.
Fralau
1
Алгол68: a = .if. .правда. .тогда. 1. Еще. 0 .fi. Это может быть выражено также как a = (. True. | 1 | 0). Как обычно, Algol68 является улучшением по сравнению с его преемниками.
Альберт ван дер Хорст
63

Для 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.

Paolo
источник
2
Поведение не идентично - q("blob", on_true, on_false)возвращает on_false, тогда как on_true if cond else on_falseвозвращает on_true. Обойти это можно заменить condс cond is not Noneв этих случаях, несмотря на то, что не является идеальным решением.
5
Почему не bool(cond)вместо cond is True? Первый проверяет достоверность cond, последний проверяет равенство указателей с Trueобъектом. Как подчеркнул @AndrewCecil, "blob"это правда, но это is not True.
Йонас Кёлкер
Ничего себе, это выглядит очень смешно! :) Технически вы можете даже написать, [on_false, on_True][cond is True]чтобы выражение стало короче.
Арсений
В этом ответе нет короткого замыкания. Если on_true и on_false стоят дорого, это плохой ответ.
Hucker
44

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

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
Бенуа Бертолон
источник
38

Есть ли в 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

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

[expression1 for element in iterable if expression2]

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

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

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

expression1 if expression1 else expression2

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

expression1 or expression2

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

Аарон Холл
источник
1
expression1 or expression2быть похожим и иметь те же недостатки / позитивы, что и expression1 || expression2в javascript
JSDBroughton
1
Спасибо, @selurvedu - это может сбить с толку, пока вы не поймете это прямо. Я выучил трудный путь, поэтому твой путь может быть не таким сложным. ;) Использование if без else в конце выражения генератора или списка будет фильтровать итерируемое. Спереди это троичная условная операция, и требуется другое. Ура !!
Аарон Холл
@AaronHall Хотя использование вами метасинтаксического expressionNдля всех экземпляров непротиворечиво, это может быть проще для понимания с помощью именования, которое отличает выражение условного теста от двух выражений результата; например, result1 if condition else result2. Это особенно очевидно при вложении (или цепочке) result1 if condition1 else result2 if condition2 else result3. Видите, насколько лучше это звучит так?
tchrist
@tchrist спасибо за обзор - если вы посмотрите на историю изменений, у этого поста в настоящее время есть две версии. Большинство других моих ответов, особенно самые лучшие, были пересмотрены снова и снова. Этот ответ никогда не привлекает мое внимание, потому что статус вики сообщества не дает мне никакой оценки за содержание, и поэтому я никогда не вижу голосов по нему. Поскольку сейчас у меня нет времени на редактирование этого вопроса, лягушка знает, когда он снова привлечет мое внимание в будущем. Я вижу, что вы отредактировали верхний ответ, так что не стесняйтесь заимствовать / процитировать мой материал из этого поста в этом (и процитируйте меня, если уместно!)
Аарон Холл
23

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

Например

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'
Сасикиран Вадди
источник
Почему не просто result = (y, x)[a < b]Почему вы используете lambdaфункцию ?
Грижеш Чаухан
5
@GrijeshChauhan Поскольку для «компилированных» выражений, например, с использованием вызова функции и т. Д., Это будет выполняться в обоих случаях. Это может быть не нужно.
glglgl
20

Тернарный условный оператор просто позволяет тестировать условие в одной строке, заменяя многострочное 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- Тернарный оператор может быть записан как вложенный 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
Али Халладжи
источник
1
Обратите внимание, что троичный оператор меньше (в памяти) и быстрее, чем вложенный if. Кроме того, ваше вложенное if-elseв действительности не является перезаписью тернарного оператора, и будет выдавать разные выходные данные для значений выбора a и b (в частности, если один является типом, который реализует странный __ne__метод).
Перкинс
19

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

[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 ''.), Поскольку, если выражение_1 становится False, тогда выражение_2 будет оцениваться из-за наличия «или» между exp_1 и exp_2.

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

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

оборота Натеш бхат
источник
Если вы хотите использовать это в контексте x = [condition] and ([expression_1] or 1) or [expression_2]и имеет expression_1значение ЛОЖЬ, xбудет 1, не expression_1. Используйте принятый ответ.
Moi
18

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

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

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

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

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

Todor
источник
5
Я предпочитаю print( 'yes' if conditionX else 'nah' )ваш ответ. :-)
frederick99
То есть, если вы хотите print()в обоих случаях - и это выглядит немного более питоническим, я должен признать :) Но что, если выражения / функции не совпадают - как print('yes') if conditionX else True- чтобы получить print()единственное правдивоеconditionX
Тодор Минаков
Чтобы добавить к замечанию Фредерика99, еще одна причина, по которой следует избегать, print('yes') if conditionX else print('nah')это то, что он дает ошибку SyntaxError в Python2.
Тьерри Латюиль
Единственная причина, по которой он выдает синтаксическую ошибку, заключается в том, что в Python 2 print - это оператор - print "yes", а в Python 3 - это функция - print("yes"). Это можно решить, используя это как утверждение, или лучше - from future import print_function.
Тодор Минаков
18
a if condition else b

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

     condition
  if           else
a                   b 
shivtej
источник
14

Одна из альтернатив условному выражению Python

"yes" if boolean else "no"

это следующее:

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

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

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

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

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

но нет альтернативы

yes() if boolean else no()

если вы хотите избежать оценки yes() и no() , потому что в

(no(), yes())[boolean]  # bad

оба no()и yes()оцениваются.

оборота Уолтер Тросс
источник
10

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

<condition> ? <expression1> : <expression2>

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

<expression1> if <condition> else <expression2>

Итак, во-первых, он оценивает состояние. Если он вернется True, выражение1 будет оценено для получения результата, в противном случае выражение2 будет оценено. Из-за механики 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'

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

ARGeo
источник
10

Как уже ответили, да, в python есть троичный оператор:

<expression 1> if <condition> else <expression 2>

Дополнительная информация:

Если <expression 1>это условие, вы можете использовать оценку короткого замыкания :

a = True
b = False

# Instead of this:
x = a if a else b

# You could use Short-cirquit evaluation:
x = a or b

PS: Конечно, оценка короткого замыкания не является троичным оператором, но часто троичный используется в случаях, когда короткого замыкания будет достаточно.

Фрэнк
источник
1
Upvote для этой short-circuitоценки.
CodeIt
7

ДА, у 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")
оборота PythonLover
источник
Я добавил пример однострочного оператора, чтобы проверить, какое число является большим, чтобы уточнить его
PythonLover
1
printдействительно не очень хороший выбор, так как это даст SyntaxError в Python2.
Тьерри Латюиль
@ Thierry Lathuille здесь я использовал функцию print (), а не оператор print, функция print для Python 3, а оператор print для Python 2
PythonLover
Вопрос уже был задан на SO, просто попробуйте его с Python 2, и вы увидите сами. 'print (' hello ') - это совершенно правильный синтаксис в Python 2.7, но то, как он анализируется, заставляет ваш код выше выдавать SyntaxError.
Тьерри Латюль
2

Python имеет троичную форму для заданий; однако может быть даже более короткая форма, о которой люди должны знать.

Очень часто нужно присваивать переменной то или иное значение в зависимости от условия.

>>> li1 = None
>>> li2 = [1, 2, 3]
>>> 
>>> if li1:
...     a = li1
... else:
...     a = li2
...     
>>> a
[1, 2, 3]

^ Это длинная форма для выполнения таких заданий.

Ниже представлена ​​троичная форма. Но это не самый лаконичный способ - см. Последний пример.

>>> a = li1 if li1 else li2
>>> 
>>> a
[1, 2, 3]
>>> 

С Python вы можете просто использовать orдля альтернативных назначений.

>>> a = li1 or li2
>>> 
>>> a
[1, 2, 3]
>>> 

Вышеприведенное работает, поскольку li1is Noneи interp интерпретирует это как False в логических выражениях. Затем interp перемещается и оценивает второе выражение, которое Noneне является пустым списком, и поэтому оно присваивается a.

Это также работает с пустыми списками. Например, если вы хотите назначить aсписок, в котором есть элементы.

>>> li1 = []
>>> li2 = [1, 2, 3]
>>> 
>>> a = li1 or li2
>>> 
>>> a
[1, 2, 3]
>>> 

Зная это, вы можете просто выполнять такие задания, когда сталкиваетесь с ними. Это также работает со строками и другими итерациями. Вы можете назначить aлюбую строку, которая не является пустой.

>>> s1 = ''
>>> s2 = 'hello world'
>>> 
>>> a = s1 or s2
>>> 
>>> a
'hello world'
>>> 

Мне всегда нравился троичный синтаксис Си, но Python делает еще один шаг вперед!

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

Тодд
источник
1

Другие ответы правильно говорят о троичном операторе Python. Я хотел бы дополнить упоминанием сценария, для которого часто используется троичный оператор, но для которого есть лучшая идиома. Это сценарий использования значения по умолчанию.

Предположим, мы хотим использовать option_valueзначение по умолчанию, если оно не установлено:

run_algorithm(option_value if option_value is not None else 10)

или просто

run_algorithm(option_value if option_value else 10)

Тем не менее, лучшее решение - просто написать

run_algorithm(option_value or 10)
user118967
источник
-2

если переменная определена, и вы хотите проверить, имеет ли она значение, вы можете просто 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
оборота ewwink
источник
1
Хотя это полезно для подобных проблем, это не троичный условный. Это работает, чтобы заменить x if x else y, но нет x if z else y.
Перкинс
-2

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

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
Яаков Бресслер
источник
-2

Я считаю громоздким синтаксис Python по умолчанию val = a if cond else b, поэтому иногда я делаю это:

iif = lambda (cond, a, b): a if cond else b
# so I can then use it like:
val = iif(cond, a, b)

Конечно, у него есть недостаток - всегда оценивать обе стороны (a и b), но синтаксис мне понятнее

Baruc Almaguer
источник
Похоже, это вдвое больше работы, больше использования оперативной памяти и больше запутанности, чем более простое val = a if cond else bутверждение.
eatsfood
-3
is_spacial=True if gender = "Female" else (True if age >= 65 else False)

**

это может быть вложено как ваша потребность. удачи

**

Это Энам
источник