Якщо 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
true a
є, то оцінюється і b
не оцінюється взагалі, а коли condition
false 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
оператор замість умовного виразу .
Майте на увазі, що деякі піфоністи нахмурилися з кількох причин:
condition ? a : b
потрійного оператора з багатьох інших мов (таких як C, C ++, Go, Perl, Ruby, Java, Javascript тощо), що може призвести до помилок, коли люди не знайомі з Python's " дивно "поведінка використовуйте його (вони можуть змінити порядок аргументів).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
потрібно повернути Істинне чи Неправдиве .
Це може бути безпечніше завжди виконувати його як:
(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 у Wikipedia
result = {1: x, 0: y}[a > b]
є ще один можливий варіант ( True
а False
насправді цілі числа зі значеннями 1
і 0
)
На жаль,
(falseValue, trueValue)[test]
рішення не має короткого замикання; таким чином і те falseValue
й інше trueValue
оцінюється незалежно від умови. Це може бути неоптимальним або навіть баггі (тобто обидва trueValue
і falseValue
можуть бути методами та мати побічні ефекти).
Одним з рішень цього було б
(lambda: falseValue, lambda: trueValue)[test]()
(виконання затягується до тих пір, поки переможець не буде відомий;)), але він вносить невідповідність між об'єктами, що дзвонять, і які не можуть викликати. Крім того, це не вирішує випадок при використанні властивостей.
І тому історія іде - вибір між трьома згаданими рішеннями є компромісом між тим, що має функцію короткого замикання, використовуючи принаймні Zython 2.5 (IMHO вже не проблема) і не схильний до trueValue
помилок " -evaluates-to-false" .
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]
У старих пітонах потрійний оператор не реалізований, але можливо його моделювати.
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 очікує третього виразу для іншого:
[expression1 if expression2 for element in iterable]
# ^-- need an else here
який піднімає a SyntaxError: invalid syntax
. Отже, вищезазначене є або неповною частиною логіки (можливо, користувач очікує, що в помилковому стані не працює), або те, що може бути призначено, це використовувати express2 як фільтр - зазначає, що наступне є законним Python:
[expression1 for element in iterable if expression2]
expression2
працює як фільтр для розуміння списку, і не є потрійним умовним оператором.
Вам може здатися дещо болісним написати наступне:
expression1 if expression1 else expression2
expression1
доведеться оцінювати двічі при використанні вище. Це може обмежити надмірність, якщо це просто локальна змінна. Тим не менш, загальна і ефективна пітонічна ідіома для цього випадку використання полягає у використанні скорочувальної 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
функцію ?
Термінальний умовний оператор просто дозволяє перевірити стан в одному рядку, замінивши багаторядковий, якщо ще зробити код компактним.
[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-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
було б істинно, коли exp1 не є хибним.
Аналогічно в
False and exp1 or exp2
Вираз exp1 не буде оцінюватися, оскільки False еквівалентний написанню 0 і виконанню "і" з 0 буде 0, але після використання exp1, оскільки "або" використовується, він оцінить вираз exp2 після "або".
Примітка: - Цей тип розгалуження за допомогою "або" і "і" може використовуватися лише тоді, коли у виразу_1 немає значення Істини Неправдивого (або 0 або Немає, або емплітиста [] або порожнього рядка ".), Оскільки якщо вираз_1 стає Неправильно, тоді вираз_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
.
Одна з альтернатив умовному вираженню Пітона
"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 поступливий D ictator F або L ife (я маю на увазі, Ґвідо ван Россум, звичайно) відкинув це (як непітонічний стиль), оскільки це досить важко зрозуміти людям, які не звикли доC
мови. Також знак двокрапки:
вже має багато застосуваньPython
. Після того, як PEP 308 був затверджений,Python
нарешті отримав власне ярликове умовне вираження (що ми використовуємо зараз):
<expression1> if <condition> else <expression2>
Отже, по-перше оцінює умову. Якщо він повернеться True
, вираження1 буде оцінено для отримання результату, інакше вираження2 буде оцінено. Завдяки механіці лінивої оцінки - буде виконано лише один вираз.
Ось кілька прикладів (умови будуть оцінені зліва направо):
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
є, None
і 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 ternary, але 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
заява.