Czy Python ma trójdzielny operator warunkowy?

Jeśli Python nie ma trójstronnego operatora warunkowego, czy możliwe jest symulowanie go za pomocą innych konstrukcji językowych?

Author: Devoted, 2008-12-27

23 answers

Tak, to było dodane w wersji 2.5.
Składnia to:

a if condition else b

Pierwszy condition jest oceniany, następnie a lub b jest zwracany na podstawie Boolean wartości condition
If condition evaluates to True a jest zwracane, else b jest zwracane.

Na przykład:

>>> 'true' if True else 'false'
'true'
>>> 'true' if False else 'false'
'false'

Zauważ, że warunki są wyrażeniem , a nie wyrażeniem. Oznacza to, że nie można używać przypisań ani pass ani innych instrukcji w warunkowe:

>>> pass if False else x = 3
  File "<stdin>", line 1
    pass if False else x = 3
          ^
SyntaxError: invalid syntax

W takim przypadku musisz użyć zwykłej if instrukcji zamiast warunkowej.


Pamiętaj, że niektórzy Pythoniści źle na to patrzą z kilku powodów:]}
  • kolejność argumentów różni się od wielu innych języków (takich jak C, Ruby, Java itp.), co może prowadzić do błędów, gdy osoby nie znające "zaskakującego" zachowania Pythona używają go (mogą odwrócić kolejność).
  • niektórzy uważają go za "nieporęczny", ponieważ jest sprzeczny z normalnym przepływem myśli (najpierw myślenie o stanie, a potem o efektach).
  • powody stylistyczne.

Jeśli masz problemy z zapamiętaniem kolejności, pamiętaj, że jeśli przeczytasz ją na głos, (prawie) powiesz, co masz na myśli. Na przykład {[12] } jest odczytywane na głos jako x will be 4 if b is greater than 8 otherwise 9.

Oficjalna dokumentacja:

 5487
Author: Vinko Vrsalovic,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-25 10:43:11

Możesz indeksować w krotkę:

(falseValue, trueValue)[test]

test musi zwrócić True lub False .
Może być bezpieczniej zawsze zaimplementować go jako:

(falseValue, trueValue)[test == True]

Lub możesz użyć wbudowanego bool() aby zapewnić wartość logiczną:

(falseValue, trueValue)[bool(<expression>)]
 616
Author: Landon Kuhn,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-10-17 07:35:10

Dla wersji przed 2.5, jest sztuczka:

[expression] and [on_true] or [on_false]

Może dać złe wyniki, gdy on_true ma wartość logiczną false.1
Chociaż ma tę zaletę, że ocenia wyrażenia od lewej do prawej, co jest jaśniejsze moim zdaniem.

1. czy istnieje odpowiednik "C"?: "Operator trójdzielny?

 253
Author: James Brady,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-01-13 07:16:48

ekspresja1 if condition else ekspresja2

>>> a = 1
>>> b = 2
>>> 1 if a > b else -1 
-1
>>> 1 if a > b else -1 if a < b else 0
-1
 162
Author: Simon Zimmermann,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-01-25 12:30:56

From the documentation :

Wyrażenia warunkowe (czasami nazywane "operatorem trójkowym") mają najniższy priorytet ze wszystkich operacji Pythona.

Wyrażenie x if C else y najpierw oblicza warunek, C (nie x); jeśliC jest prawdziwe, x jest obliczane i zwracana jest jego wartość; w przeciwnym razie, y jest obliczane i zwracana jest jego wartość.

Zobacz PEP 308 aby uzyskać więcej informacji na temat warunkowego wyrażenia.

Nowy od wersji 2.5.

 108
Author: Michael Burr,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-10-17 07:43:53

Operator dla wyrażenia warunkowego w Pythonie został dodany w 2006 roku jako część propozycja ulepszenia Pythona 308. Jego forma różni się od zwykłego operatora ?: i wynosi:

<expression1> if <condition> else <expression2>

Co jest równoważne:

if <condition>: <expression1> else: <expression2>
Oto przykład:]}
result = x if a > b else y

Inna składnia, która może być użyta (zgodna z wersjami sprzed 2.5):

result = (lambda:y, lambda:x)[a > b]()

Gdzie operandy są leniwie oceniane .

Innym sposobem jest indeksowanie krotki (która nie jest zgodny z operatorem warunkowym większości innych języków):

result = (y, x)[a > b]

Lub jawnie skonstruowany słownik:

result = {True: x, False: y}[a > b]

Inną (mniej wiarygodną), ale prostszą metodą jest użycie operatorów and i or:

result = (a > b) and x or y

To jednak nie zadziała, jeśli x będzie False.

Możliwym obejściem jest utworzenie x iy list lub krotek, jak w poniższym:

result = ((a > b) and [x] or [y])[0]

Lub:

result = ((a > b) and (x,) or (y,))[0]

Jeśli pracujesz ze słownikami, zamiast używać warunkowe trójwarstwowe, można skorzystać z get(key, default), na przykład:

shell = os.environ.get('SHELL', "/bin/sh")

Źródło: ?: w Pythonie w Wikipedii

 82
Author: kenorb,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-08-07 14:22:32

@ up:

Niestety,

(falseValue, trueValue)[test]

Rozwiązanie nie ma zwarcia; dlatego zarówno falseValue, jak i trueValue są oceniane niezależnie od warunku. Może to być nieoptymalne lub nawet błędne (tj. zarówno trueValue, jak i falseValue mogą być metodami i mieć skutki uboczne).

Jednym z rozwiązań byłoby

(lambda: falseValue, lambda: trueValue)[test]()

(wykonanie opóźnione do czasu poznania zwycięzcy;)), ale wprowadza niespójność między obiektami wywoływalnymi i nie wywoływalnymi. Dodatkowo, nie rozwiązuje sprawy przy użyciu właściwości.

I tak dalej-wybór pomiędzy 3 wspomnianymi rozwiązaniami to kompromis między posiadaniem funkcji zwarcia, używaniem co najmniej Pythona 2.5 (IMHO nie jest już problemem) a nie podatnością na błędy "trueValue-evaluates-to-false".

 74
Author: gorsky,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-14 09:45:44

Dla Pythona 2.5 i nowszych istnieje specjalna składnia:

[on_true] if [cond] else [on_false]

W starszych Pythonach Operator trójkowy nie jest zaimplementowany, ale można go symulować.

cond and on_true or on_false

Istnieje jednak potencjalny problem, który Jeśli cond ewaluuje do True i on_true ewaluuje do False, to zwracane jest on_false zamiast on_true. Jeśli chcesz to zachowanie metoda jest OK, w przeciwnym razie użyj tego:

{True: on_true, False: on_false}[cond is True] # is True, not == True

Które mogą być owinięte przez:

def q(cond, on_true, on_false)
    return {True: on_true, False: on_false}[cond is True]

I użył tego sposób:

q(cond, on_true, on_false)

Jest kompatybilny ze wszystkimi wersjami Pythona.

 49
Author: Paolo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-04-25 12:02:06

Operator trójdzielny w różnych językach programowania

Tutaj staram się pokazać jakąś istotną różnicę w ternary operator pomiędzy kilkoma językami programowania.

Operator Ternary w Javascript

var a = true ? 1 : 0;
# 1
var b = false ? 1 : 0;
# 0

Operator Ternary w Ruby

a = true ? 1 : 0
# 1
b = false ? 1 : 0
# 0

Operator trójdzielny w Scali

val a = true ? 1 | 0
# 1
val b = false ? 1 | 0
# 0

Operator trójdzielny w R programowanie

a <- if (TRUE) 1 else 0
# 1
b <- if (FALSE) 1 else 0
# 0

operator trójkowy w Pythonie

a = 1 if True else 0
# 1
b = 1 if False else 0
# 0

Teraz możesz zobaczyć piękno języka python. jest bardzo czytelny i łatwy w utrzymaniu.

 41
Author: Simplans,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-12 20:37:17

Możesz często znaleźć

cond and on_true or on_false

Ale to prowadzi do problemu, gdy on_true = = 0

>>> x = 0
>>> print x == 0 and 0 or 1 
1
>>> x = 1
>>> print x == 0 and 0 or 1 
1

Gdzie można oczekiwać dla normalnego operatora trójdzielnego tego wyniku

>>> x = 0
>>> print 0 if x == 0 else 1 
0
>>> x = 1
>>> print 0 if x == 0 else 1 
1
 32
Author: Benoit Bertholon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-01-14 15:56:09

Absolutnie i jest to niezwykle łatwe do zrozumienia.

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
 29
Author: BattleDrum,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-01-20 20:01:14

Czy Python ma trójdzielny operator warunkowy?

Tak. Z pliku :
test: or_test ['if' or_test 'else' test] | lambdef

Część zainteresowania to:

or_test ['if' or_test 'else' test]

Tak więc trójdzielna operacja warunkowa ma postać:

expression1 if expression2 else expression3

expression3 będzie leniwie oceniane (tzn. oceniane tylko wtedy, gdy {[9] } jest false w kontekście logicznym). A ze względu na rekurencyjną definicję, można je łączyć w nieskończoność (choć może to być uważane za zły styl.)

expression1 if expression2 else expression3 if expression4 else expression5 # and so on

Uwaga przy użyciu:

Należy pamiętać, że po każdym {[10] } musi następować znak else. Osoby uczące się kompilacji list i wyrażeń generatora mogą uznać to za trudną lekcję do nauczenia się - poniższe nie będą działać, ponieważ Python oczekuje trzeciego wyrażenia dla else: {]}

[expression1 if expression2 for element in iterable]
#                          ^-- need an else here

Co podnosi SyntaxError: invalid syntax. Tak więc powyższe jest albo niekompletnym kawałkiem logiki (być może użytkownik oczekuje no-op w fałszywym stanie), albo może być zamierzone użycie expression2 jako filtra-zauważa, że poniżej znajduje się Python prawny:

[expression1 for element in iterable if expression2]

expression2 działa jako filtr dla zrozumienia listy i jest , a nie trójdzielnym operatorem warunkowym.

Składnia alternatywna dla węższej litery:

Może cię to trochę bolesne napisać:

expression1 if expression1 else expression2

expression1 będzie musiał być oceniany dwukrotnie przy powyższym użyciu. Może ograniczyć redundancję, jeśli jest to po prostu zmienna lokalna. Jednak powszechnym i występującym idiomem Pythonicznym dla tego przypadku użycia jest użycie or zachowanie skrótu:

expression1 or expression2

Co jest równoważne w semantyce. Zauważ, że niektóre przewodniki po stylach mogą ograniczyć to użycie ze względu na przejrzystość - to naprawdę pakuje wiele znaczeń w bardzo małą składnię.

 22
Author: Aaron Hall,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-08-08 18:56:31

Symulacja operatora trójdzielnego Pythona.

Na przykład

a, b, x, y = 1, 2, 'a greather than b', 'b greater than a'
result = (lambda:y, lambda:x)[a > b]()

Wyjście:

'b greater than a'
 15
Author: Sasikiran Vaddi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-11-20 10:44:12

Możesz to zrobić:-

[condition] and [expression_1] or [expression_2] ;

Przykład:-

print(number%2 and "odd" or "even")

To wyświetli "nieparzyste", jeśli liczba jest nieparzysta lub "parzyste", jeśli liczba jest parzysta.


Wynik: - jeśli warunek jest prawdziwy to jest wykonywane exp_1, w przeciwnym razie jest wykonywane exp_2.

Notatka: - 0, None, False , emptylist, emptyString ocenia jako False. I wszelkie dane inne niż 0 są ewaluowane jako True.

Oto jak to działa:

Jeśli warunek [warunek] staje się "True" wtedy będzie obliczane wyrażenie formula_1 ale nie wyrażenie formula_2 . Jeśli " i " coś z 0 (zero), wynik zawsze będzie fasle .więc w poniższym oświadczeniu,

0 and exp

Wyrażenie exp nie będzie w ogóle oceniane, ponieważ "i" z 0 zawsze będzie oceniane do zera i nie ma potrzeby oceniania wyrażenia . Tak działa sam kompilator we wszystkich językach.

W

1 or exp

Wyrażenie exp nie będzie w ogóle oceniane od " or" z 1 zawsze będzie 1. Więc nie będzie kłopotać się z oceną wyrażenia exp, ponieważ wynik i tak będzie 1 . (metody optymalizacji kompilatora).

Ale w przypadku

True and exp1 or exp2

Drugie wyrażenie exp2 nie będzie oceniane, ponieważ True and exp1 będzie prawdziwe, gdy exp1 nie jest fałszywe .

Podobnie w

False and exp1 or exp2

Wyrażenie exp1 nie będzie oceniane, ponieważ False jest równoważne z zapisem 0, a zrobienie "i" z 0 będzie samo w sobie równe 0, ale po użyciu exp1, Ponieważ "lub" będzie ocenia wyrażenie exp2 po "lub".


Uwaga: - tego rodzaju rozgałęzienia za pomocą "or " I" and " mogą być użyte tylko wtedy, gdy wyrażenie formula_1 nie ma wartości False (lub 0 lub None lub emptylist [ ] lub emptystring '".) ponieważ jeśli wyrażenie formula_1 stanie się False , to wyrażenie formula_2 będzie obliczane ze względu na obecność " lub " pomiędzy wyrażeniem formula_1 a wyrażeniem formula_2.

W przypadku, gdy nadal chcesz, aby to działało dla wszystkich przypadków, niezależnie od tego, co prawda exp_1 i exp_2 wartości są, zrób to :-

[condition] and ([expression_1] or 1) or [expression_2] ;

 10
Author: Natesh bhat,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-08-20 07:48:54
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
 9
Author: ox.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-05-07 13:02:06

Bardziej wskazówka niż odpowiedź (nie trzeba powtarzać oczywistego po raz setny), ale czasami używam go jako jednego skrótu w takich konstrukcjach:

if conditionX:
    print('yes')
else:
    print('nah')

, staje się:

print('yes') if conditionX else print('nah')

Niektórzy (wielu :) mogą marszczyć brwi na to jako niepythoniczne (nawet Ruby-owskie:), ale osobiście uważam to za bardziej naturalne - tzn. jak byś to normalnie wyraził, plus nieco bardziej wizualnie w dużych blokach kodu.

 9
Author: Todor,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-05-23 19:16:26

Trójliniowy operator warunkowy pozwala po prostu przetestować warunek w pojedynczej linii, zastępując wieloliniowy if-else, czyniąc kod zwartym.

Składnia:

[on_true] if [wyrażenie] else [on_false]

1-Prosta metoda użycia operatora trójdzielnego:

# 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-bezpośrednia metoda użycia krotek, słownika i lambda:

# 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

Operator 3 - Ternary może być zapisany jako zagnieżdżony 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")

Powyższe podejście można zapisać jako:

# 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
 9
Author: Ali Hallaji,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-04 14:02:17

Tak, możesz go używać w ten sposób:

is_fat = True
state = "fat" if is_fat else "not fat"

Czytaj więcej o trójdzielny operator warunkowy

 8
Author: Daniel Taub,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-06-10 13:14:08

Tak.

>>> b = (True if 5 > 4 else False)
>>> print b
True
 4
Author: Alejandro Blasco,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-16 16:36:22

Tak:

Powiedzmy, że chcesz dać zmiennej x jakąś wartość, jeśli jakiś bool jest true i podobnie

X = 5 jeśli coś innego x = 10

X = [jakaś wartość] if [if this is true pierwsza wartość ewaluuje] else [inna wartość ewaluuje]

 2
Author: Elad Goldenberg,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-14 06:25:11

Składnia: Operator Trójargumentowy będzie podany jako:

[on_true] if [expression] else [on_false]

E. g

x, y = 25, 50
big = x if x < y else y
print(big)
 2
Author: Saurabh Chandra Patel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-31 20:23:58

Istnieje opcja ternary, jak podano w innych odpowiedziach, ale można ją również symulować za pomocą "lub", jeśli sprawdzasz wartość logiczną lub None:

>>> a = False
>>> b = 5
>>> a or b
5

>>> a = None
>>> a or b
5
 1
Author: Meow,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-12-08 19:05:13

Jeśli zmienna jest zdefiniowana i chcesz sprawdzić, czy ma wartość, możesz po prostu 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)

Wyświetli

no Input
no Input
no Input
hello
['Hello']
True
 1
Author: ewwink,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-26 16:22:58