Если в Python нет троичного условного оператора, можно ли смоделировать его с помощью других языковых конструкций?
Да, оно было добавлено в версии 2.5. Синтаксис выражения следующий:
a if condition else b
Сначала оценивается условие
, затем оценивается и возвращается ровно одно из a
или b
на основе булевского значения условия
. Если condition
имеет значение True
, то a
оценивается и возвращается, а b
игнорируется, или иначе, когда b
оценивается и возвращается, а a
игнорируется.
Это позволяет осуществлять короткое замыкание, потому что когда условие
истинно, оценивается только a
, а b
не оценивается вообще, а когда условие
ложно, оценивается только 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
выражение вместо условного выражения.
Имейте в виду, что некоторые Pythonисты не одобряют это по нескольким причинам:
condition ? a : b
из многих других языков (таких как C, C++, Go, Perl, Ruby, Java, Javascript и т.д.), что может привести к ошибкам, когда люди, незнакомые с "удивительным" поведением Python, используют его (они могут изменить порядок аргументов).if
' может быть очень полезным и сделать ваш сценарий более лаконичным, он действительно усложняет ваш код).Если вам трудно запомнить порядок, то помните, что при чтении вслух вы (почти) говорите то, что имеете в виду. Например, x = 4 if b > 8 else 9
будет прочитано вслух как x будет 4, если b больше 8, иначе 9
.
Официальная документация:
Вы можете индексировать в кортеж:
(falseValue, trueValue)[test]
test
должен вернуть True или False.
Может быть безопаснее всегда реализовывать это как:
(falseValue, trueValue)[test == True]
или вы можете использовать встроенный bool ()
, чтобы обеспечить значение Boolean:
(falseValue, trueValue)[bool(<expression>)]
Для версий, предшествующих 2.5, есть одна хитрость:
[expression] and [on_true] or [on_false]
Это может дать неверные результаты, когда on_true
имеет булево значение false.1
Хотя у него есть преимущество в том, что он оценивает выражения слева направо, что, на мой взгляд, более понятно.
1. Существует ли эквивалент троичного оператора "?:" языка Си?
< код > < i > < выражение 1 > < / i > < b > / b > < i > < условие > < / i > < b >
а = 1
б = 2
1, если > б еще -1
# Выход -1
1, если > b еще -1, если < b еще 0
# Выход -1
Из [документации]:
Условные выражения (иногда называемые "тернарным оператором") имеют самый низкий приоритет среди всех операций Python.
Выражение
x if C else y
сначала оценивает условие, C (not x); если C истинно, x оценивается и возвращается его значение; в противном случае, y оценивается и возвращается его значение.Более подробно об условных выражениях см. в PEP 308.
Новое с версии 2.5.
Оператор для условного выражения в Python был добавлен в 2006 году как часть Python Enhancement Proposition 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]()
где операнды лазильно оценены.
Другой способ - индексировать кортеж (который не согласуется с условным оператором большинства других языков):
result = (y, x)[a > b]
или явно построенный словарь:
result = {True: x, False: y}[a > b]
Другой (менее надежный), но более простой метод - использовать операторы и
и или
:
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 в Википедии < / sup >
К сожалению,
(falseValue, trueValue)[test]
Решение не имеет поведения короткого замыкания; таким образом, falseValue
и trueValue
оцениваются независимо от состояния. Это может быть неоптимальным или даже глючным (т.е. оба trueValue
и falseValue
могут быть методами и иметь побочные эффекты).
Одним из решений этого было бы
(lambda: falseValue, lambda: trueValue)[test]()
(исполнение задерживается до тех пор, пока победитель не станет известен;)), но оно вводит несоответствие между вызываемыми и не вызываемыми объектами. Кроме того, это не решает случай при использовании свойств.
И так, история гласит: выбор между 3 упомянутыми решениями - это компромисс между наличием функции короткого замыкания, использующей, по крайней мере, Zython 2.5 (ИМХО больше не проблема) и не склонной к «trueValue» -оценкам -false "ошибки.
Последовательный оператор на разных языках программирования
Здесь я просто пытаюсь показать некоторые важные различия в «постоянном операторе» между парой языков программирования.
- Последовательный оператор в Javascript *
var a = true ? 1 : 0;
# 1
var b = false ? 1 : 0;
# 0
- Последовательный оператор в Ruby *
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]
У старых Питонов троичный оператор не реализован, но его можно смоделировать.
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 ожидает третье выражение для другого:
[expression1 if expression2 for element in iterable]
# ^-- need an else here
который поднимает SyntaxError: неверный синтаксис
.
Таким образом, вышеизложенное является либо неполной частью логики (возможно, пользователь ожидает отсутствия операции в ложном состоянии), либо можно использовать выражение 2 в качестве фильтра - отмечает, что следующим является законный Python:
[expression1 for element in iterable if expression2]
expression2
работает как фильтр для понимания списка и не является * троичным условным оператором.
Вам может быть несколько больно писать следующее:
expression1 if expression1 else expression2
expression1
придется оценивать дважды с вышеуказанным использованием. Это может ограничить избыточность, если это просто локальная переменная. Тем не менее, общая и эффективная питонская идиома для этого варианта использования состоит в том, чтобы использовать сокращающее поведение or
:
expression1 or expression2
что эквивалентно в семантике. Обратите внимание, что некоторые руководства по стилю могут ограничивать это использование из-за ясности - оно имеет большое значение в очень малом синтаксисе.
Моделирование троичного оператора питона.
Например
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'
Вы можете сделать это :-
[условие] и [expression_1] или [expression_2];
Пример: -
print (число% 2 и "странный" или "четный")
Это напечатало бы «странно», если число нечетное, или «четное», если число четное.
Примечание: - 0, Нет, Ложь, emptylist, emptyString оценивается как Ложь. И любые данные, кроме 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 и exp1
будут True, когда exp1 не является ложным .
Точно так же в
False and exp1 or exp2
Выражение exp1 не будет оцениваться, поскольку False эквивалентно написанию 0, а выполнение «и» с 0 само по себе будет равно 0, но после exp1, поскольку используется «или», оно оценит выражение exp2 после «или» .
Примечание: - Этот вид ветвления с использованием «или» и «и» может использоваться только в том случае, если выражение_1 не имеет значения Истины False (или 0 или None или emptylist [] или emptystring ''.) поскольку, если выражение_1 становится ложным, выражение_2 будет оцениваться из-за присутствия «или» между exp_1 и exp_2.
Если вы все еще хотите, чтобы это работало для всех случаев, независимо от того, каковы значения истинности exp_1 и exp_2, сделайте это: -
[условие] и ([expression_1] или 1) или [expression_2];
Терничный условный оператор просто позволяет протестировать условие в одной строке, заменяя многострочный if-else, делая код компактным.
[on_true] if [выражение] 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 conditionX:
print('yes')
else:
print('nah')
, становится:
print('yes') if conditionX else print('nah')
Некоторые (многие :) могут осуждать это как непитоническое (даже рубиновое :), но я лично нахожу это более естественным - т.е. как бы вы это выразили нормально, плюс немного более визуально привлекательным в больших блоках кода.
Многие языки программирования, полученные из C
, обычно имеют следующий синтаксис троичного условного оператора:
<condition> ? <expression1> : <expression2>
Сначала
Python
B enevolent D ictator F или L ife (я имею в виду Гвидо ван Россума, конечно) отклонил его (как непитонический стиль) , так как это довольно трудно понять людям, не привыкшим к языку C. Кроме того, знак двоеточия:
уже имеет много применений вPython
. После утверждения PEP 308 «Python» наконец получил собственное условное выражение ярлыка (что мы используем сейчас):
<expression1> if <condition> else <expression2>
Итак, во-первых, он оценивает состояние. Если он вернет True
, expression1 будет оценен, чтобы дать результат, в противном случае expression2 будет оценен. Из-за механики Ленивая оценка - будет выполнено только одно выражение.
Вот несколько примеров (условия будут оцениваться слева направо):
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'
Надеюсь, это поможет.
ДА, у питона есть троичный оператор, вот синтаксис и пример кода, чтобы продемонстрировать то же самое :)
#[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 [условное выражение][1] заключается в следующем:
{True:"yes", False:"no"}[boolean]
который имеет следующее приятное расширение:
{True:"yes", False:"no", None:"maybe"}[boolean_or_none]
Кратчайший альтеративный остаток:
("no", "yes")[boolean]
но альтернативы нет, если вы хотите избежать оценки yes ()
и no ()
в следующем:
yes() if [condition] else no()
[1]: https://mail.python.org/pipermail/python-dev/2005-сентябрь / 056846.html
Как уже было сказано, да, в питоне есть троичный оператор
<expression 1> if <condition> else <expression 2>
Дополнительная информация:
Если < выражение 1 >
- это условие, которое вы можете использовать Оценка короткого замыкания:
а = правда
б = ложно
# Вместо этого:
x = a, если a, b
# Вы можете использовать оценку короткого циркания:
х = а или б
PS: Конечно, оценка короткого замыкания не является троичным оператором, но часто троичный используется в тех случаях, когда короткого замыкания будет достаточно.