Есть ли в Python троичный условный оператор?
Если в Python нет тернарного условного оператора, возможно ли имитировать его, используя другие языковые конструкции?
43 ответа
Да, это было добавлено в версии 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
В таком случае вы должны использовать нормальный 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
,
Официальная документация:
Вы можете индексировать в кортеж:
(falseValue, trueValue)[test]
test
должен вернуть True или False.
Может быть безопаснее всегда реализовывать это как:
(falseValue, trueValue)[test == True]
или вы можете использовать встроенный bool()
чтобы обеспечить логическое значение:
(falseValue, trueValue)[bool(<expression>)]
Для версий до 2.5 есть хитрость:
[expression] and [on_true] or [on_false]
Это может дать неправильные результаты, когда on_true
имеет ложное логическое значение.1
Хотя он имеет преимущество оценки выражений слева направо, что, на мой взгляд, более понятно.
выражение1, если условие еще выражение2
>>> 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 вычисляется и возвращается его значение; в противном случае вычисляется y и возвращается его значение.См. PEP 308 для более подробной информации об условных выражениях.
Новое с версии 2.5.
Оператор для условного выражения в 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 в Википедии
@up:
К сожалению,
(falseValue, trueValue)[test]
решение не имеет поведения короткого замыкания; таким образом, и falseValue, и trueValue оцениваются независимо от условия. Это может быть неоптимальным или даже ошибочным (то есть как trueValue, так и falseValue могут быть методами и иметь побочные эффекты).
Одним из решений этого было бы
(lambda: falseValue, lambda: trueValue)[test]()
(выполнение откладывается до тех пор, пока победитель не станет известен;)), но это вносит несоответствие между вызываемыми и не вызываемыми объектами. Кроме того, это не решает проблему при использовании свойств.
Итак, история продолжается: выбор между 3 упомянутыми решениями - это компромисс между наличием функции короткого замыкания, использованием как минимум Python 2.5 (ИМХО больше не проблема) и отсутствием склонности к "trueValue-оценки-к-ложному". ошибки.
Тернарный оператор на разных языках программирования
Здесь я просто пытаюсь показать некоторые важные различия в 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
Теперь вы можете увидеть красоту языка Python. его очень удобочитаемый и ремонтопригодный.
Для 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.
Вы можете часто находить
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
Есть ли в 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
что эквивалентно в семантике. Обратите внимание, что некоторые руководства по стилю могут ограничивать это использование из соображений ясности - оно действительно вкладывает много смысла в очень маленький синтаксис.
Одной из альтернатив условному выражению Python является следующее:
{True:"yes", False:"no"}[boolean]
который имеет следующее хорошее расширение:
{True:"yes", False:"no", None:"maybe"}[boolean_or_none]
Самая короткая альтернатива остается:
("no", "yes")[boolean]
но нет альтернативы, если вы хотите избежать оценки обоих yes()
а также no()
В следующих:
yes() if [condition] else no()
Как уже было сказано, да, в 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: Конечно, оценка короткого замыкания не является тернарным оператором, но часто тернарный используется в тех случаях, когда короткого замыкания будет достаточно.
Имитация троичного оператора питона.
Например
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'
Абсолютно, и это невероятно легко понять.
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
a if condition else b
Просто запомните эту пирамиду, если у вас возникли проблемы с запоминанием:
condition
if else
a b
Ответ Винко Врсаловича достаточно хорош. Остается только одно:
Обратите внимание, что условные выражения - это выражение , а не инструкция . Это означает, что вы не можете использовать операторы присваивания или
pass
или другие операторы в условном выражении
Оператор Walrus в Python 3.8
После того, как этот оператор моржа был введен в Python 3.8, кое-что изменилось.
(a := 3) if True else (b := 5)
дает
a = 3
и
b is not defined
,
(a := 3) if False else (b := 5)
дает и, и
c = (a := 3) if False else (b := 5)
дает
c = 5
,
a is not defined
и
b = 5
.
Даже если это может показаться некрасивым, присваивания можно выполнять внутри условных выражений после Python 3.8. Все равно лучше использовать нормальный
if
заявление вместо этого в этом случае.
Тернарный условный оператор просто позволяет тестировать условие в одной строке, заменяя многострочное 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
Скорее подсказка, чем ответ (не нужно повторять очевидное в течение сотых раз), но я иногда использую его как ярлык oneliner в таких конструкциях:
if conditionX:
print('yes')
else:
print('nah')
, становится:
print('yes') if conditionX else print('nah')
Некоторые (многие:) могут нахмуриться, что это не пифонично (даже ruby-ish:), но я лично нахожу это более естественным - то есть, как бы вы выразились как обычно, плюс немного более визуально привлекательным в больших блоках кода.
Вы можете сделать это:-
[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 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] ;
Многие языки программирования получены из C
обычно имеют следующий синтаксис троичного условного оператора:
<condition> ? <expression1> : <expression2>
Во-первых,
Python
Бедный D иктатор F или L ife (я имею в виду Гвидо ван Россума, конечно) отверг это (как непифонический стиль), так как это довольно трудно понять людям, не привыкшим кC
язык. Кроме того, знак двоеточия:
уже имеет много применений вPython
, После того, как ПКП 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'
Надеюсь это поможет.
ДА, у 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")
Другие ответы правильно говорят о тернарном операторе 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)
Синтаксис тернарного оператора в Python:
[on_true] if [expression] else [on_false]
Используя этот синтаксис, вот как мы могли бы переписать приведенный выше код, используя тернарный оператор Python:
game_type = 'home'
shirt = 'white' if game_type == 'home' else 'green'
Это все еще довольно ясно, но намного короче. Обратите внимание, что выражение может быть выражением любого типа, включая вызов функции, который возвращает значение, оцениваемое как True или False.
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
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]
>>>
Вышеуказанное работает с li1
является None
и interp рассматривает это как False в логических выражениях. Затем interp переходит и оценивает второе выражение, которое не являетсяNone
и это не пустой список - поэтому он присваивается.
Это также работает с пустыми списками. Например, если вы хотите назначить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'
>>>
Мне всегда нравился тернарный синтаксис C, но Python делает еще один шаг вперед!
Я понимаю, что некоторые могут сказать, что это не лучший стилистический выбор, потому что он основан на механике, которая не сразу очевидна для всех разработчиков. Я лично не согласен с этой точкой зрения. Python - это язык с богатым синтаксисом и множеством идиоматических уловок, которые не сразу бросаются в глаза даблеру. Но чем больше вы изучаете и понимаете механизмы лежащей в основе системы, тем больше вы это цените.
Да, вы можете использовать это так:
is_fat = True
state = "fat" if is_fat else "not fat"
Подробнее о тройной условный оператор
Pythonic способ делать вещи:
"true" if var else "false"
Но всегда существует и другой способ выполнения троичного условия:
"true" and var or "false"
Есть несколько способов. Самый простой — использовать условие внутри метода «print».
Вы можете использовать
print("Twenty" if number == 20 else "Not twenty")
Что эквивалентно:
if number == 20:
print("Twenty")
else:
print("Not twenty")
Таким образом, можно напечатать более двух операторов. Например:
if number == 20:
print("Twenty")
elif number < 20:
print("Lesser")
elif 30 > number > 20:
print("Between")
else:
print("Greater")
можно записать как:
print("Twenty" if number == 20 else "Lesser" if number < 20 else "Between" if 30 > number > 20 else "Greater")