Если в Python нет тернарного условного оператора, возможно ли имитировать его, используя другие языковые конструкции?
6051
Если в Python нет тернарного условного оператора, возможно ли имитировать его, используя другие языковые конструкции?
case [...] { when ... then ...} [ else ... ] end
аналогичный эффект, но никак не троичный.Ответы:
Да, это было добавлено в версии 2.5. Синтаксис выражения:
Сначала
condition
оценивается, затем точно один изa
илиb
оценивается и возвращается на основе логического значенияcondition
. Еслиcondition
оценивается какTrue
, тоa
оценивается и возвращается, ноb
игнорируется, или же когдаb
оценивается и возвращается, ноa
игнорируется.Это допускает короткое замыкание, потому что, когда
condition
истинно только значениеa
, оценивается иb
вообще не оценивается, а когдаcondition
ложно толькоb
оценивается иa
не оценивается вообще.Например:
Обратите внимание, что условные выражения являются выражением , а не утверждением . Это означает, что вы не можете использовать операторы присваивания
pass
или другие операторы в условном выражении :Однако вы можете использовать условные выражения для присваивания переменной следующим образом:
Думайте об условном выражении как о переключении между двумя значениями. Это очень полезно, когда вы находитесь в ситуации «одного значения или другого», но больше ничего не делает.
Если вам нужно использовать операторы, вы должны использовать обычный
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
)Вы можете индексировать в кортеж:
test
должен вернуть True или False .Может быть безопаснее всегда реализовывать это как:
или вы можете использовать встроенное,
bool()
чтобы обеспечить логическое значение:источник
(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 есть хитрость:
Он может давать неправильные результаты, когда
on_true
имеет ложное логическое значение. 1Хотя он имеет преимущество оценки выражений слева направо, что, на мой взгляд, более понятно.
1. Есть ли эквивалент троичного оператора C?
источник
<expression 1> if <condition> else <expression 2>
источник
Из документации :
Новое с версии 2.5.
источник
Оператор для условного выражения в Python был добавлен в 2006 году как часть предложения 308 по улучшению Python . Его форма отличается от обычного
?:
оператора, и это:что эквивалентно:
Вот пример:
Другой синтаксис, который можно использовать (совместим с версиями до 2.5):
где операнды лениво оцениваются .
Другой способ - индексирование кортежа (что не согласуется с условным оператором большинства других языков):
или явно сконструированный словарь:
Другим (менее надежным), но более простым способом является использование
and
иor
операторов:однако это не сработает, если
x
будетFalse
.Возможный обходной путь состоит в том, чтобы сделать
x
иy
списки или кортежи как в следующем:или:
Если вы работаете со словарями, вместо использования троичного условного выражения, вы можете воспользоваться
get(key, default)
, например:Источник: ?: В Python в Википедии
источник
result = {1: x, 0: y}[a > b]
другой возможный вариант (True
иFalse
на самом деле целые числа со значениями1
и0
)К сожалению,
решение не имеет поведения короткого замыкания; при этом оба
falseValue
иtrueValue
оцениваются независимо от состояния. Это может быть неоптимальным или даже багги (т.е. какtrueValue
иfalseValue
могут быть методы и имеют побочные эффекты).Одним из решений этого было бы
(выполнение откладывается до тех пор, пока победитель не станет известен;)), но оно вносит несоответствие между вызываемыми и не вызываемыми объектами. Кроме того, это не решает проблему при использовании свойств.
Итак, история продолжается: выбор между 3 упомянутыми решениями является компромиссом между наличием функции короткого замыкания, использованием как минимум Зython 2.5 (ИМХО больше не проблема) и отсутствием склонности к ошибкам «
trueValue
-оценивается-ложно» ,источник
if else if
.Тернарный оператор на разных языках программирования
Здесь я просто пытаюсь показать некоторые важные различия
ternary operator
между парой языков программирования.источник
Для Python 2.5 и новее существует специальный синтаксис:
В старых Pythons троичный оператор не реализован, но его можно смоделировать.
Тем не менее, существует потенциальная проблема, которая, если
cond
оцениваетTrue
иon_true
оценивает,False
затемon_false
возвращается вместоon_true
. Если вы хотите это поведение, метод в порядке, в противном случае используйте это:который может быть упакован:
и использовал этот способ:
Он совместим со всеми версиями 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]
чтобы выражение стало короче.Вы можете часто находить
но это приводит к проблеме, когда on_true == 0
где вы ожидаете для нормального троичного оператора этот результат
источник
Да. Из файла грамматики :
Интересная часть:
Итак, троичная условная операция имеет вид:
expression3
будет лениво оцениваться (то есть оцениваться только еслиexpression2
ложно в логическом контексте). И из-за рекурсивного определения вы можете связывать их бесконечно (хотя это может считаться плохим стилем).Примечание по использованию:
Обратите внимание, что каждый
if
должен сопровождатьсяelse
. Люди, изучающие списки и выражения-генераторы, могут найти этот урок трудным для изучения - следующее не сработает, так как Python ожидает третьего выражения для else:который поднимает
SyntaxError: invalid syntax
. Таким образом, вышеприведенное является либо неполной частью логики (возможно, пользователь ожидает запрета в ложном состоянии), либо может быть предназначено для использования expression2 в качестве фильтра - отмечает, что следующее является допустимым Python:expression2
работает как фильтр для понимания списка и не является троичным условным оператором.Альтернативный синтаксис для более узкого случая:
Вам может быть немного больно писать следующее:
expression1
нужно будет оценить дважды с использованием вышеуказанного. Это может ограничить избыточность, если это просто локальная переменная. Тем не менее, распространенная и эффективная идиома Pythonic для этого варианта использования заключается в использованииor
сокращенного поведения:что эквивалентно в семантике. Обратите внимание, что некоторые руководства по стилю могут ограничивать это использование из соображений ясности - оно содержит много смысла в очень небольшом синтаксисе.
источник
expression1 or expression2
быть похожим и иметь те же недостатки / позитивы, что иexpression1 || expression2
в javascriptexpressionN
для всех экземпляров непротиворечиво, это может быть проще для понимания с помощью именования, которое отличает выражение условного теста от двух выражений результата; например,result1 if condition else result2
. Это особенно очевидно при вложении (или цепочке)result1 if condition1 else result2 if condition2 else result3
. Видите, насколько лучше это звучит так?Имитация троичного оператора питона.
Например
вывод:
источник
result = (y, x)[a < b]
Почему вы используетеlambda
функцию ?Тернарный условный оператор просто позволяет тестировать условие в одной строке, заменяя многострочное if-else, делая код компактным.
Синтаксис:
1- Простой метод использования тернарного оператора:
2- Прямой метод использования кортежей, словаря и лямбды:
3- Тернарный оператор может быть записан как вложенный if-else:
Вышеуказанный подход можно записать так:
источник
if-else
в действительности не является перезаписью тернарного оператора, и будет выдавать разные выходные данные для значений выбора a и b (в частности, если один является типом, который реализует странный__ne__
метод).ты можешь сделать это :-
[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 (ноль), результат всегда будет быстрым. Так в приведенном ниже утверждении,
Выражение exp не будет оцениваться вообще, так как «и» с 0 всегда будет равняться нулю, и нет необходимости оценивать выражение. Так работает сам компилятор на всех языках.
В
выражение exp вообще не будет оцениваться, так как «или» с 1 всегда будет равно 1. Таким образом, оно не будет мешать вычислению выражения exp, так как результат все равно будет равен 1. (методы оптимизации компилятора).
Но в случае
Второе выражение exp2 не будет оцениваться, поскольку
True and exp1
будет True, если exp1 не false.Точно так же в
Выражение 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
. Используйте принятый ответ.Больше подсказка, чем ответ (не нужно повторять очевидное в течение сотых раз), но я иногда использую его как ярлык для однотипных конструкций в таких конструкциях:
, становится:
Некоторые (многие :) могут посчитать это неуместным (даже рубиновым :), но я лично нахожу это более естественным - то есть, как бы вы это выразили нормально, плюс немного более визуально привлекательным в больших блоках кода.
источник
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()
иno()
, потому что воба
no()
иyes()
оцениваются.источник
Многие языки программирования, производные от которых
C
обычно имеют следующий синтаксис троичного условного оператора:Итак, во-первых, он оценивает состояние. Если он вернется
True
, выражение1 будет оценено для получения результата, в противном случае выражение2 будет оценено. Из-за механики Lazy Evaluation - будет выполнено только одно выражение.Вот несколько примеров (условия будут оцениваться слева направо):
Тернарные операторы могут быть соединены последовательно:
Следующий такой же, как предыдущий:
Надеюсь это поможет.
источник
Как уже ответили, да, в python есть троичный оператор:
Дополнительная информация:
Если
<expression 1>
это условие, вы можете использовать оценку короткого замыкания :PS: Конечно, оценка короткого замыкания не является троичным оператором, но часто троичный используется в случаях, когда короткого замыкания будет достаточно.
источник
short-circuit
оценки.ДА, у python есть троичный оператор, вот синтаксис и пример кода, чтобы продемонстрировать то же самое :)
источник
print
действительно не очень хороший выбор, так как это даст SyntaxError в Python2.Python имеет троичную форму для заданий; однако может быть даже более короткая форма, о которой люди должны знать.
Очень часто нужно присваивать переменной то или иное значение в зависимости от условия.
^ Это длинная форма для выполнения таких заданий.
Ниже представлена троичная форма. Но это не самый лаконичный способ - см. Последний пример.
С Python вы можете просто использовать
or
для альтернативных назначений.Вышеприведенное работает, поскольку
li1
isNone
и interp интерпретирует это как False в логических выражениях. Затем interp перемещается и оценивает второе выражение, котороеNone
не является пустым списком, и поэтому оно присваивается a.Это также работает с пустыми списками. Например, если вы хотите назначить
a
список, в котором есть элементы.Зная это, вы можете просто выполнять такие задания, когда сталкиваетесь с ними. Это также работает со строками и другими итерациями. Вы можете назначить
a
любую строку, которая не является пустой.Мне всегда нравился троичный синтаксис Си, но Python делает еще один шаг вперед!
Я понимаю, что некоторые могут сказать, что это не очень хороший стилистический выбор, потому что он основан на механике, которая не сразу очевидна для всех разработчиков. Я лично не согласен с этой точкой зрения. Python - это язык с богатым синтаксисом и множеством идиоматических трюков, которые не сразу бросаются в глаза даблеру. Но чем больше вы изучаете и понимаете механику базовой системы, тем больше вы цените ее.
источник
Другие ответы правильно говорят о троичном операторе Python. Я хотел бы дополнить упоминанием сценария, для которого часто используется троичный оператор, но для которого есть лучшая идиома. Это сценарий использования значения по умолчанию.
Предположим, мы хотим использовать
option_value
значение по умолчанию, если оно не установлено:или просто
Тем не менее, лучшее решение - просто написать
источник
если переменная определена, и вы хотите проверить, имеет ли она значение, вы можете просто
a or b
будет выводить
источник
x if x else y
, но нетx if z else y
.Аккуратный способ связать несколько операторов:
источник
Я считаю громоздким синтаксис Python по умолчанию
val = a if cond else b
, поэтому иногда я делаю это:Конечно, у него есть недостаток - всегда оценивать обе стороны (a и b), но синтаксис мне понятнее
источник
val = a if cond else b
утверждение.**
**
источник