Если в Python нет тернарного условного оператора, возможно ли имитировать его, используя другие языковые конструкции?
case [...] { when ... then ...} [ else ... ] end
аналогичный эффект, но никак не троичный.
Если в Python нет тернарного условного оператора, возможно ли имитировать его, используя другие языковые конструкции?
case [...] { when ... then ...} [ else ... ] end
аналогичный эффект, но никак не троичный.
Ответы:
Да, это было добавлено в версии 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 " «Удивительно» поведение использовать его (они могут изменить порядок аргументов).if
» может быть очень полезным и сделать ваш скрипт более кратким, он действительно усложнит ваш код)Если у вас возникают проблемы с запоминанием порядка, помните, что когда вы читаете вслух, вы (почти) говорите, что имеете в виду. Например, x = 4 if b > 8 else 9
читается вслух как x will be 4 if b is greater than 8 otherwise 9
.
Официальная документация:
f(x) = |x| = x if x > 0 else -x
для математиков это звучит очень естественно. Вы также можете понять это, как и A в большинстве случаев, за исключением случаев, когда C, тогда вы должны вместо этого делать B ...
z = 3 + x if x < y else y
. Если x=2
и y=1
, вы можете ожидать, что это даст 4, но это на самом деле приведет к 1. z = 3 + (x if x > y else y)
это правильное использование.
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
)
Вы можете индексировать в кортеж:
(falseValue, trueValue)[test]
test
должен вернуть True или False .
Может быть безопаснее всегда реализовывать это как:
(falseValue, trueValue)[test == True]
или вы можете использовать встроенное, bool()
чтобы обеспечить логическое значение:
(falseValue, trueValue)[bool(<expression>)]
(lambda: print("a"), lambda: print("b"))[test==true]()
[]
s, может быть произвольным выражением. Кроме того, для безопасности вы можете явно проверить на правдивость, написав [bool(<expression>)]
. Эта bool()
функция существует с v2.2.1.
True
и False
в качестве ключей: {True:trueValue, False:falseValue}[test]
я не знаю, является ли это менее эффективным, но он, по крайней мере, избегает всего «элегантный» против «некрасивых» дебатов. Там нет двусмысленности, что вы имеете дело с логическим, а не с Int.
Для версий до 2.5 есть хитрость:
[expression] and [on_true] or [on_false]
Он может давать неправильные результаты, когда on_true
имеет ложное логическое значение. 1
Хотя он имеет преимущество оценки выражений слева направо, что, на мой взгляд, более понятно.
<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
Из документации :
Условные выражения (иногда называемые «троичным оператором») имеют самый низкий приоритет среди всех операций Python.
Выражение
x if C else y
сначала оценивает условие, C ( не x ); если 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 в Википедии
result = {1: x, 0: y}[a > b]
другой возможный вариант ( True
и False
на самом деле целые числа со значениями 1
и 0
)
К сожалению,
(falseValue, trueValue)[test]
решение не имеет поведения короткого замыкания; при этом оба falseValue
и trueValue
оцениваются независимо от состояния. Это может быть неоптимальным или даже багги (т.е. как trueValue
и falseValue
могут быть методы и имеют побочные эффекты).
Одним из решений этого было бы
(lambda: falseValue, lambda: trueValue)[test]()
(выполнение откладывается до тех пор, пока победитель не станет известен;)), но оно вносит несоответствие между вызываемыми и не вызываемыми объектами. Кроме того, это не решает проблему при использовании свойств.
Итак, история продолжается: выбор между 3 упомянутыми решениями является компромиссом между наличием функции короткого замыкания, использованием как минимум Зython 2.5 (ИМХО больше не проблема) и отсутствием склонности к ошибкам « trueValue
-оценивается-ложно» ,
if else if
.
Здесь я просто пытаюсь показать некоторые важные различия 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 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.
q("blob", on_true, on_false)
возвращает on_false
, тогда как on_true if cond else on_false
возвращает on_true
. Обойти это можно заменить cond
с cond is not None
в этих случаях, несмотря на то, что не является идеальным решением.
bool(cond)
вместо cond is True
? Первый проверяет достоверность cond
, последний проверяет равенство указателей с True
объектом. Как подчеркнул @AndrewCecil, "blob"
это правда, но это is not True
.
[on_false, on_True][cond is True]
чтобы выражение стало короче.
Вы можете часто находить
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
что эквивалентно в семантике. Обратите внимание, что некоторые руководства по стилю могут ограничивать это использование из соображений ясности - оно содержит много смысла в очень небольшом синтаксисе.
expression1 or expression2
быть похожим и иметь те же недостатки / позитивы, что и expression1 || expression2
в javascript
expressionN
для всех экземпляров непротиворечиво, это может быть проще для понимания с помощью именования, которое отличает выражение условного теста от двух выражений результата; например, result1 if condition else result2
. Это особенно очевидно при вложении (или цепочке) result1 if condition1 else result2 if condition2 else result3
. Видите, насколько лучше это звучит так?
Имитация троичного оператора питона.
Например
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
функцию ?
Тернарный условный оператор просто позволяет тестировать условие в одной строке, заменяя многострочное if-else, делая код компактным.
[on_true] if [expression] else [on_false]
# 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
# 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
# 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
if-else
в действительности не является перезаписью тернарного оператора, и будет выдавать разные выходные данные для значений выбора a и b (в частности, если один является типом, который реализует странный __ne__
метод).
ты можешь сделать это :-
[condition] and [expression_1] or [expression_2] ;
Пример:-
print(number%2 and "odd" or "even")
Это выведет «нечетное», если число нечетное, или «четное», если число четное.
Примечание: - 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
. Используйте принятый ответ.
Больше подсказка, чем ответ (не нужно повторять очевидное в течение сотых раз), но я иногда использую его как ярлык для однотипных конструкций в таких конструкциях:
if conditionX:
print('yes')
else:
print('nah')
, становится:
print('yes') if conditionX else print('nah')
Некоторые (многие :) могут посчитать это неуместным (даже рубиновым :), но я лично нахожу это более естественным - то есть, как бы вы это выразили нормально, плюс немного более визуально привлекательным в больших блоках кода.
print( 'yes' if conditionX else 'nah' )
ваш ответ. :-)
print()
в обоих случаях - и это выглядит немного более питоническим, я должен признать :) Но что, если выражения / функции не совпадают - как print('yes') if conditionX else True
- чтобы получить print()
единственное правдивоеconditionX
print('yes') if conditionX else print('nah')
это то, что он дает ошибку SyntaxError в Python2.
print "yes"
, а в Python 3 - это функция - print("yes")
. Это можно решить, используя это как утверждение, или лучше - from future import print_function
.
Одна из альтернатив условному выражению 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()
оцениваются.
Многие языки программирования, производные от которых 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'
Надеюсь это поможет.
Как уже ответили, да, в 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: Конечно, оценка короткого замыкания не является троичным оператором, но часто троичный используется в случаях, когда короткого замыкания будет достаточно.
short-circuit
оценки.
ДА, у 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")
print
действительно не очень хороший выбор, так как это даст SyntaxError в Python2.
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
is 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 - это язык с богатым синтаксисом и множеством идиоматических трюков, которые не сразу бросаются в глаза даблеру. Но чем больше вы изучаете и понимаете механику базовой системы, тем больше вы цените ее.
Другие ответы правильно говорят о троичном операторе 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)
если переменная определена, и вы хотите проверить, имеет ли она значение, вы можете просто 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
x if x else y
, но нет x if z else y
.
Аккуратный способ связать несколько операторов:
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
Я считаю громоздким синтаксис 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), но синтаксис мне понятнее
val = a if cond else b
утверждение.