Czy Python ma trójskładnikowy operator warunkowy?

6041

Jeśli Python nie ma trójskładnikowego operatora warunkowego, czy można go symulować przy użyciu innych konstrukcji języka?

poświęcony
źródło
149
W oficjalnej dokumentacji Python 3.0, o której mowa w powyższym komentarzu, jest to określane jako „wyrażenia warunkowe” i jest bardzo kryptycznie zdefiniowane. Ta dokumentacja nawet nie zawiera terminu „trójskładnikowy”, więc trudno byłoby znaleźć go za pośrednictwem Google, chyba że dokładnie wiesz, czego szukać. Dokumentacja w wersji 2 jest nieco bardziej pomocna i zawiera link do „PEP 308” , który zawiera wiele interesujących kontekstów historycznych związanych z tym pytaniem.
nobar
26
„trójskładnikowy” (posiadający trzy wejścia) jest następczą właściwością tego impelmentacji, a nie definiującą właściwością pojęcia. np .: SQL ma case [...] { when ... then ...} [ else ... ] endpodobny efekt, ale wcale nie jest trójskładnikowy.
user313114,
10
również ISO / IEC 9899 (standard języka programowania C) sekcja 6.5.15 nazywa to „operatorem warunkowym”
użytkownik313114
9
Wikipedia szczegółowo opisuje to w artykule „ ?: ”.
HelloGoodbye,
9
W latach, które upłynęły od komentarza nobara, dokumentacja wyrażeń warunkowych została zaktualizowana, by powiedzieć Wyrażenia warunkowe (czasami nazywane „operatorem potrójnym”) ...
Scott Martin

Odpowiedzi:

7039

Tak, został dodany w wersji 2.5. Składnia wyrażenia to:

a if condition else b

Najpierw conditionjest obliczany, a następnie dokładnie jeden z nich alub bjest oceniany i zwracany na podstawie wartości logicznejcondition . Jeśli conditionocenia to True, to ajest oceniane i zwracane, ale bjest ignorowane, lub kiedy bjest oceniane i zwracane, ale ajest ignorowane.

Pozwala to na zwarcie, ponieważ gdy conditionjest prawdziwe tylko ajest oceniana i bnie jest oceniana w ogóle, ale jeśli conditionjest fałszywe tylko bjest oceniana i anie jest oceniana w ogóle.

Na przykład:

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

Pamiętaj, że warunkowe są wyrażeniem , a nie wyrażeniem . Oznacza to, że nie można używać instrukcji przypisania passani innych instrukcji w wyrażeniu warunkowym :

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

Możesz jednak użyć wyrażeń warunkowych, aby przypisać zmienną w następujący sposób:

x = a if True else b

Pomyśl o wyrażeniu warunkowym jako przełączaniu między dwiema wartościami. Jest to bardzo przydatne, gdy znajdujesz się w sytuacji „jednej lub innej wartości”, ale nie robi wiele więcej.

Jeśli potrzebujesz użyć instrukcji, musisz użyć normalnej if instrukcji zamiast wyrażenia warunkowego .


Pamiętaj, że niektórzy Pythoniści patrzą na to z dezaprobatą z kilku powodów:

  • Kolejność argumentów różni się od klasycznego condition ? a : boperatora trójskładnikowego w wielu innych językach (takich jak C, C ++, Go, Perl, Ruby, Java, JavaScript itp.), Co może prowadzić do błędów, gdy ludzie nie znają Pythona „ zaskakujące "użyj go (mogą odwrócić kolejność argumentów).
  • Niektórzy uważają to za „nieporęczne”, ponieważ jest sprzeczne z normalnym przepływem myśli (najpierw myślenie o stanie, a potem o skutkach).
  • Powody stylistyczne. (Chociaż „wstawka if” może być naprawdę przydatna i sprawia, że ​​skrypt jest bardziej zwięzły, to naprawdę komplikuje kod)

Jeśli masz problemy z zapamiętaniem kolejności, pamiętaj, że czytając na głos, (prawie) mówisz, co masz na myśli. Na przykład x = 4 if b > 8 else 9jest czytany na głos jako x will be 4 if b is greater than 8 otherwise 9.

Oficjalna dokumentacja:

Vinko Vrsalovic
źródło
268
Kolejność może wydawać się dziwna dla programistów, jednak f(x) = |x| = x if x > 0 else -xdla matematyków brzmi to bardzo naturalnie. Możesz również zrozumieć to tak, jak A w większości przypadków, z wyjątkiem sytuacji, gdy C to powinieneś zrobić B zamiast tego ...
yota
120
Zachowaj ostrożność podczas wykonywania operacji. Na przykład linia z = 3 + x if x < y else y. Jeśli x=2i y=1, możesz oczekiwać, że da to 4, ale tak naprawdę da 1. z = 3 + (x if x > y else y)to prawidłowe użycie.
Kal Zekdor,
11
Chodziło o to, że jeśli chcesz wykonać dodatkowe oceny po ocenie warunkowej, takie jak dodanie wartości do wyniku, musisz dodać dodatkowe wyrażenie po obu stronach ( z = 3 + x if x < y else 3 + y) lub zgrupować warunek ( z = 3 + (x if x < y else y)lub z = (x if x < y else y) + 3)
Kal Zekdor
4
@MrGeek, rozumiem, co masz na myśli, więc po prostu zagnieżdżasz operacje: `` foo '', jeśli Bool else („bar”, jeśli Bool else „foobar”) `
Dimesio
3
Programiści potrzebują dokładniejszego poprawnego sformułowania nawet bardziej niż matematyk, ponieważ w matematyce zawsze istnieje ucieczka od podstawowych pojęć. Przekonującym argumentem jest operator%, naśladowanie sposobu używania „mod” w matematyce byłoby katastrofą. Więc nie, nie akceptuję twojego argumentu. To jest jak przylgnięcie do jednostek imperialnych. Groetjes Albert
Albert van der Horst
795

Możesz indeksować do krotki:

(falseValue, trueValue)[test]

testmusi zwrócić wartość Prawda lub Fałsz .
Bezpieczniej jest zawsze go wdrożyć, ponieważ:

(falseValue, trueValue)[test == True]

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

(falseValue, trueValue)[bool(<expression>)]
Landon Kuhn
źródło
589
Zauważ, że ten zawsze ocenia wszystko, podczas gdy konstrukcja if / else ocenia tylko wygrywające wyrażenie.
SilverbackNet,
117
(lambda: print("a"), lambda: print("b"))[test==true]()
Dustin Getz
15
Należy zauważyć, że to, co znajduje się w []literach, może być dowolnym wyrażeniem. Ponadto, dla bezpieczeństwa możesz wyraźnie przetestować prawdziwość, pisząc [bool(<expression>)]. Ta bool()funkcja jest dostępna od wersji 2.2.1.
martineau
12
Zrobiłem podobną sztuczkę - tylko raz lub dwa, ale zrobiłem to - indeksując do słownika za pomocą klawiszy Truei Falsejako: {True:trueValue, False:falseValue}[test] Nie wiem, czy jest to mniej wydajne, ale przynajmniej unika całości debata „elegancka” a „brzydka”. Nie ma wątpliwości, że masz do czynienia z wartością logiczną zamiast int.
JDM
338

W przypadku wersji wcześniejszych niż 2.5 istnieje sztuczka:

[expression] and [on_true] or [on_false]

Może dawać błędne wyniki, gdy on_true ma fałszywą wartość boolowską. 1
Chociaż ma tę zaletę, że ocenia wyrażenia od lewej do prawej, co moim zdaniem jest wyraźniejsze.

1. Czy istnieje odpowiednik operatora trójskładnikowego „?”: „?

James Brady
źródło
67
Rozwiązanie polega na użyciu (test i [true_value] lub [false_value]) [0], co pozwala uniknąć tej pułapki.
ThomasH
5
Operator trójskładnikowy zwykle wykonuje się szybciej (czasem o 10–25%).
wulkan
7
@volcano Czy masz dla mnie źródło?
OrangeTux,
4
@OrangeTux Oto zdemontowany kod . Przy użyciu metody sugerowanej przez ThomasH byłoby jeszcze wolniej.
mbomb007
265

<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
Simon Zimmermann
źródło
83
Ten podkreśla główny cel operatora trójskładnikowego: wybór wartości. Pokazuje także, że więcej niż jeden trójskładnik można połączyć w jedno wyrażenie.
Roy Tinker,
6
@Craig, zgadzam się, ale warto również wiedzieć, co się stanie, gdy nie będzie nawiasów. W prawdziwym kodzie ja również wstawiałbym wyraźne pareny.
Jon Coombs,
158

Z dokumentacji :

Wyrażenia warunkowe (czasem nazywane „operatorem potrójnym”) mają najniższy priorytet ze wszystkich operacji w języku Python.

Wyrażenie x if C else ynajpierw ocenia warunek, C ( nie x ); jeśli C jest prawdą, x jest obliczane i zwracana jest jego wartość; w przeciwnym razie y jest obliczane, a jego wartość zwracana.

Zobacz PEP 308, aby uzyskać więcej informacji na temat wyrażeń warunkowych.

Nowość od wersji 2.5.

Michael Burr
źródło
120

Operator wyrażenia warunkowego w języku Python został dodany w 2006 r. Jako część propozycji ulepszenia języka Python 308 . Jego forma różni się od zwykłego ?:operatora i jest:

<expression1> if <condition> else <expression2>

co jest równoważne z:

if <condition>: <expression1> else: <expression2>

Oto przykład:

result = x if a > b else y

Inna składnia, której można użyć (kompatybilna z wersjami wcześniejszymi niż 2.5):

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

gdzie operandy są leniwie oceniane .

Innym sposobem jest indeksowanie krotki (co nie jest zgodne 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 niezawodną), ale prostszą metodą jest użycie andi oroperatory:

result = (a > b) and x or y

jednak to nie zadziała, jeśli xbyłoby False.

Możliwym obejściem jest wykonanie xi ywyświetlenie list lub krotek w następujący sposób:

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

lub:

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

Jeśli pracujesz ze słownikami, zamiast trójkowego warunku, możesz get(key, default)na przykład skorzystać z :

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

Źródło: ?: W Python na Wikipedii

kenorb
źródło
1
result = {1: x, 0: y}[a > b]jest innym możliwym wariantem ( Truei Falsefaktycznie są liczbami całkowitymi z wartościami 1i 0)
Walter Tross
98

Niestety

(falseValue, trueValue)[test]

rozwiązanie nie ma zwarć; więc zarówno falseValuei trueValuesą oceniane niezależnie od warunków. To może być panującymi lub nawet buggy (czyli zarówno trueValuei falseValuemoże być metody i mają skutki uboczne).

Jednym z takich rozwiązań byłoby

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

(wykonanie opóźnione do momentu poznania zwycięzcy;)), ale wprowadza niespójność między obiektami, które można wywoływać, a obiektami, których nie można wywołać. Ponadto nie rozwiązuje problemu przy korzystaniu z właściwości.

I tak oto historia - wybór pomiędzy 3 wymienionymi rozwiązaniami jest kompromisem między posiadaniem funkcji zwarcia, używaniem co najmniej honython 2.5 (IMHO już nie stanowi problemu) i niepodatnością na błędy „ trueValue-szacowania-do-fałszowania” .

gorsky
źródło
2
Podczas gdy krotka trick lambdas działa, zajmuje około 3 razy więcej niż operator trójskładnikowy. To może być rozsądny pomysł, jeśli może zastąpić długi łańcuch if else if.
Perkins,
72

Operator trójskładnikowy w różnych językach programowania

Tutaj próbuję tylko pokazać ważną różnicę ternary operatormiędzy kilkoma językami programowania.

Operator trójskładnikowy w JavaScript

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

Trójskładnikowy w Ruby

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

Operator trójskładnikowy w Scali

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

Operator trójskładnikowy w programowaniu R.

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

Operator trójskładnikowy w języku Python

a = 1 if True else 0
# 1
b = 1 if False else 0
# 0
Simplans
źródło
5
Może to zabrzmieć opiniotwórczo; ale w gruncie rzeczy mówi ono, że składnia Pythona może być zrozumiana przez osobę, która nigdy nie widziała operatora trójskładnikowego, podczas gdy bardzo niewiele osób zrozumie bardziej typową składnię, chyba że najpierw zostanie im powiedziane, co to znaczy.
fralau
1
Algol68: a = .if. .prawdziwe. .następnie. 1 .el. 0 .fi. Można to również wyrazić a = (. True. | 1 | 0) Jak zwykle Algol68 stanowi ulepszenie w stosunku do swoich następców.
Albert van der Horst,
63

Dla Python 2.5 i nowszych istnieje specjalna składnia:

[on_true] if [cond] else [on_false]

W starszych pytonach operator trójskładnikowy nie jest zaimplementowany, ale można go zasymulować.

cond and on_true or on_false

Istnieje jednak potencjalny problem, który jeśli zostanie condoceniony Truei on_trueoceni, Falseto on_falsezostanie zwrócony zamiast on_true. Jeśli chcesz mieć takie 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 można owinąć:

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

i używał w ten sposób:

q(cond, on_true, on_false)

Jest kompatybilny ze wszystkimi wersjami Pythona.

Paolo
źródło
2
Zachowanie nie jest identyczne - q("blob", on_true, on_false)zwraca on_false, natomiast on_true if cond else on_falsezwraca on_true. Rozwiązaniem jest zastąpienie condze cond is not Nonew tych przypadkach, mimo że nie jest to idealne rozwiązanie.
5
Dlaczego nie bool(cond)zamiast cond is True? Pierwszy sprawdza prawdziwość cond, drugi sprawdza równość wskaźnika z Trueobiektem. Jak podkreśla @AndrewCecil, "blob"jest to prawda, ale tak jest is not True.
Jonas Kölker,
Wow, to wygląda naprawdę cholernie! :) Technicznie możesz nawet pisać, [on_false, on_True][cond is True]więc wyrażenie staje się krótsze.
Arseny
W tej odpowiedzi nie ma zwarcia. Jeśli wywołanie on_true i on_false jest drogie, jest to zła odpowiedź.
Hucker
44

Często możesz znaleźć

cond and on_true or on_false

ale prowadzi to 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ć tego od normalnego operatora trójskładnikowego

>>> x = 0
>>> print 0 if x == 0 else 1 
0
>>> x = 1
>>> print 0 if x == 0 else 1 
1
Benoit Bertholon
źródło
38

Czy Python ma trójskładnikowy operator warunkowy?

Tak. Z pliku gramatyki :

test: or_test ['if' or_test 'else' test] | lambdef

Część zainteresowania to:

or_test ['if' or_test 'else' test]

Tak więc trójskładnikowa operacja warunkowa ma postać:

expression1 if expression2 else expression3

expression3będzie leniwie oceniany (to znaczy oceniany tylko wtedy, gdy expression2jest fałszywy w kontekście logicznym). Ze względu na definicję rekurencyjną można je łączyć w nieskończoność (choć może to uważać za zły styl).

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

Uwaga dotycząca użytkowania:

Zauważ, że po każdym ifmusi nastąpić znak else. Dla osób uczących się ze zrozumieniem list i wyrażeń generatora może to być trudna lekcja - poniższe czynności nie będą działać, ponieważ Python oczekuje trzeciego wyrażenia dla innej osoby:

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

co podnosi SyntaxError: invalid syntax. Tak więc powyższe jest albo niekompletną logiką (być może użytkownik spodziewa się braku operacji w fałszywym stanie), albo może być zamierzone użycie wyrażenia2 jako filtru - zauważa, że ​​następujące jest legalne Python:

[expression1 for element in iterable if expression2]

expression2działa jako filtr do zrozumienia listy i nie jest trójskładnikowym operatorem warunkowym.

Alternatywna składnia dla wąskiego przypadku:

Może być trochę bolesne napisać następujące rzeczy:

expression1 if expression1 else expression2

expression1będzie musiał zostać oceniony dwukrotnie przy powyższym użyciu. Może ograniczyć nadmiarowość, jeśli jest to po prostu zmienna lokalna. Jednak powszechnym i wydajnym idiomem Pythona dla tego przypadku użycia orjest zachowanie skrótu:

expression1 or expression2

co jest równoważne w semantyce. Zwróć uwagę, że niektóre przewodniki po stylach mogą ograniczać to użycie ze względu na przejrzystość - dodaje dużo znaczenia w bardzo małej składni.

Aaron Hall
źródło
1
expression1 or expression2są podobne i mają takie same wady / zalety jak expression1 || expression2w javascript
zalety
1
Dzięki, @selurvedu - może to być mylące, dopóki nie zrozumiesz. Nauczyłem się trudnej drogi, więc twoja droga może nie być tak trudna. ;) Użycie if bez else na końcu wyrażenia generatora lub zrozumienia listy przefiltruje iterowalny. Z przodu jest to trójskładnikowa operacja warunkowa i wymaga drugiej. Twoje zdrowie!!
Aaron Hall
@AaronHall Chociaż korzystanie z metasyntaktyki expressionNwe wszystkich instancjach jest spójne, łatwiejsze jest zrozumienie nazewnictwa, które odróżniało warunkowe wyrażenie testowe od dwóch wyrażeń wynikowych; np result1 if condition else result2. Jest to szczególnie widoczne, gdy gniazdowania (aka łańcuchowym) result1 if condition1 else result2 if condition2 else result3. Widzisz, o ile lepiej to czyta w ten sposób?
tchrist
@ tchrist dzięki za recenzję - jeśli spojrzysz na historię zmian, ten post ma obecnie dwie wersje. Większość moich pozostałych odpowiedzi, szczególnie te najważniejsze, były wielokrotnie odwiedzane. Ta odpowiedź nigdy nie zwraca mojej uwagi, ponieważ status wiki społeczności nie daje mi uznania za treść, więc nigdy nie widzę w niej żadnych głosów. Ponieważ tak naprawdę nie mam teraz czasu na edycję w tym temacie, żaba wie, kiedy ponownie zwróci moją uwagę w przyszłości. Widzę, że zredagowałeś najwyższą odpowiedź, więc możesz pożyczyć / zacytować mój materiał z tego postu w tym (i cytuj mnie, jeśli apropos!)
Aaron Hall
23

Symulacja trójskładnikowego języka python.

Na przykład

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

wynik:

'b greater than a'
Sasikiran Vaddi
źródło
Dlaczego nie po prostu result = (y, x)[a < b]dlaczego korzystasz z lambdafunkcji ?
Grijesh Chauhan
5
@GrijeshChauhan Ponieważ w wyrażeniach „zgodnych”, np. Obejmujących wywołanie funkcji itp., Byłoby to wykonane w obu przypadkach. To może nie być potrzebne.
glglgl
20

Trójskładnikowy operator warunkowy pozwala po prostu przetestować warunek w jednym wierszu, zastępując multilinię, jeśli w przeciwnym razie kod jest zwarty.

Składnia:

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

1- Prosta metoda użycia operatora trójskładnikowego:

# 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żywania 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

3- Operator trójskładnikowy można zapisać jako zagnieżdżony, jeśli:

# 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
Ali Hallaji
źródło
1
Zauważ, że operator trójskładnikowy jest mniejszy (w pamięci) i szybszy niż zagnieżdżony, jeśli. Również zagnieżdżone if-elsenie jest w rzeczywistości przepisywaniem operatora trójskładnikowego i będzie generować różne dane wyjściowe dla wybranych wartości aib (szczególnie jeśli jest to typ, który implementuje dziwną __ne__metodę).
Perkins,
19

możesz to zrobić :-

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

Przykład:-

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

Spowoduje to wydrukowanie „nieparzystej”, jeśli liczba jest nieparzysta, lub „parzystej”, jeśli liczba jest parzysta.


Wynik: - Jeśli warunek jest spełniony, exp_1 jest wykonywane, w przeciwnym razie exp_2 jest wykonywane.

Uwaga :- 0, Brak, Fałsz, emptylist, emptyString ocenia się jako False. A wszelkie dane inne niż 0 mają wartość True.

Oto jak to działa:

jeśli warunek [warunek] stanie się „Prawdą”, wówczas wyrażenie_1 zostanie ocenione, ale nie wyrażenie_2. Jeśli my "i" coś z 0 (zero), wynik zawsze będzie fasle. Więc w poniższej instrukcji,

0 and exp

Wyrażenie exp nie będzie w ogóle oceniane, ponieważ „i” z 0 zawsze będzie oceniać na zero i nie ma potrzeby oceny 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, ponieważ „lub” z 1 zawsze będzie wynosić 1. Więc nie będzie kłopotać się oceną wyrażenia exp, ponieważ wynik i tak będzie wynosił 1. (metody optymalizacji kompilatora).

Ale w przypadku

True and exp1 or exp2

Drugie wyrażenie exp2 nie będzie odtąd oceniane True and exp1 byłoby prawdziwe, gdy exp1 nie jest fałszywe.

Podobnie w

False and exp1 or exp2

Wyrażenie exp1 nie zostanie ocenione, ponieważ False jest równoznaczne z zapisaniem 0 i zrobieniem „, a” z 0 byłoby 0, ale po exp1, ponieważ użyto „lub”, oceni wyrażenie exp2 po „lub”.


Uwaga: - Tego rodzaju rozgałęzienia za pomocą „lub” i „i” można użyć tylko wtedy, gdy wyrażenie_1 nie ma wartości Prawdy Fałsz (lub 0 lub Brak lub pusta lista [] lub pusty ciąg „”.), Ponieważ jeśli wyrażenie_1 staje się Fałsz, wówczas wyrażenie_2 zostanie ocenione ze względu na obecność „lub” między exp_1 a exp_2.

Jeśli nadal chcesz, aby działał we wszystkich przypadkach, niezależnie od wartości prawdy exp_1 i exp_2, wykonaj następujące czynności:

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

Natesh bhat
źródło
Jeśli chcesz użyć jej w kontekście x = [condition] and ([expression_1] or 1) or [expression_2]i expression_1FALSE, xbędzie 1, nie expression_1. Użyj zaakceptowanej odpowiedzi.
moi
18

Bardziej wskazówka niż odpowiedź (nie trzeba powtarzać oczywistości dla setnego czasu), ale czasami używam jej jako skrótu oneliner w takich konstrukcjach:

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

, staje się:

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

Niektórzy (wielu :) mogą się na to uważać za niepytonicznych (nawet rubinowych :), ale osobiście uważam, że jest to bardziej naturalne - tj. Jak wyrażasz to normalnie, a także trochę bardziej atrakcyjne wizualnie w dużych blokach kodu.

Todor
źródło
5
Wolę print( 'yes' if conditionX else 'nah' )twoją odpowiedź. :-)
frederick99
To znaczy, jeśli chcesz print()w obu przypadkach - i wygląda trochę bardziej pytonicznie, muszę przyznać :) Ale co, jeśli wyrażenia / funkcje nie są takie same - jak print('yes') if conditionX else True- aby uzyskać print()jedyną prawdęconditionX
Todor
Aby dodać do uwagi Frederick99, kolejnym powodem, dla którego należy tego unikać, print('yes') if conditionX else print('nah')jest to, że daje błąd SyntaxError w Python2.
Thierry Lathuille,
Jedynym powodem, dla którego powoduje błąd składniowy, jest to, że w Python 2 print jest instrukcją - print "yes"podczas gdy w Python 3 jest funkcją - print("yes"). Można to rozwiązać, używając go jako instrukcji lub lepiej - from future import print_function.
Todor Minakov
18
a if condition else b

Zapamiętaj tę piramidę, jeśli masz problemy z zapamiętaniem:

     condition
  if           else
a                   b 
shivtej
źródło
14

Jedna z alternatyw dla wyrażenia warunkowego Pythona

"yes" if boolean else "no"

jest następujący:

{True:"yes", False:"no"}[boolean]

który ma następujące ładne rozszerzenie:

{True:"yes", False:"no", None:"maybe"}[boolean_or_none]

Najkrótszą alternatywą pozostaje:

("no", "yes")[boolean]

ale nie ma alternatywy dla

yes() if boolean else no()

jeśli chcesz uniknąć oceny yes() i no() , ponieważ w

(no(), yes())[boolean]  # bad

zarówno no()i yes()są oceniane.

Walter Tross
źródło
10

Wiele języków programowania pochodzących z Czazwyczaj ma następującą składnię trójskładnikowego operatora warunkowego:

<condition> ? <expression1> : <expression2>

Początkowo Python B enevolent D ictator F lub L IFE (mam na myśli Guido van Rossum, oczywiście) odrzucił (jako non-pythonic stylu), ponieważ jest to dość trudne do zrozumienia dla ludzi nie wykorzystywanych do Cjęzyka. Również znak dwukropka :ma już wiele zastosowań Python. Po zatwierdzeniu PEP 308Python ostatecznie otrzymało własne wyrażenie warunkowe skrótu (którego używamy teraz):

<expression1> if <condition> else <expression2>

Więc po pierwsze ocenia warunek. Jeśli zwróci True, wyrażenie1 zostanie ocenione, aby dać wynik, w przeciwnym razie wyrażenie2 zostanie ocenione. Ze względu na mechanikę Lazy Evaluation - zostanie wykonane tylko jedno wyrażenie.

Oto kilka przykładów (warunki będą oceniane od lewej do prawej):

pressure = 10
print('High' if pressure < 20 else 'Critical')

# Result is 'High'

Operatory trójskładnikowe można łączyć szeregowo:

pressure = 5
print('Normal' if pressure < 10 else 'High' if pressure < 20 else 'Critical')

# Result is 'Normal'

Poniższy jest taki sam jak poprzedni:

pressure = 5

if pressure < 20:
    if pressure < 10:
        print('Normal')
    else:
        print('High')
else:
    print('Critical')

# Result is 'Normal'

Mam nadzieję że to pomoże.

ARGeo
źródło
10

Jak już odpowiedziano, tak, w pythonie jest operator trójskładnikowy:

<expression 1> if <condition> else <expression 2>

Dodatkowe informacje:

Jeśli <expression 1>jest to warunek, możesz użyć oceny krótkiego obwodu :

a = True
b = False

# Instead of this:
x = a if a else b

# You could use Short-cirquit evaluation:
x = a or b

PS: Oczywiście ocena zwarcia nie jest operatorem trójskładnikowym, ale często trójskładnik jest używany w przypadkach, w których zwarcie byłoby wystarczające.

Szczery
źródło
1
Głosuj za tą short-circuitoceną.
CodeIt
7

TAK, python ma operator trójskładnikowy, oto składnia i przykładowy kod pokazujący to samo :)

#[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")
PythonLover
źródło
Dodałem przykład instrukcji
jednowierszowej,
1
printnaprawdę nie jest dobrym wyborem, ponieważ da to błąd SyntaxError w Python2.
Thierry Lathuille,
@Thierry Lathuille tutaj Użyłem funkcji print () not print, funkcja print jest dla Pythona 3, a print jest dla Pythona 2
PythonLover
Pytanie zostało już zadane na SO, po prostu spróbuj z Python 2, a zobaczysz sam. 'print (' hello ') jest doskonale poprawną składnią w Pythonie 2.7, ale sposób, w jaki jest analizowany, powoduje, że kod powyżej generuje błąd SyntaxError.
Thierry Lathuille,
2

Python ma trójskładnikową formę przypisań; jednak może istnieć jeszcze krótsza forma, o której ludzie powinni wiedzieć.

Bardzo często konieczne jest przypisanie do zmiennej jednej lub innej wartości w zależności od warunku.

>>> li1 = None
>>> li2 = [1, 2, 3]
>>> 
>>> if li1:
...     a = li1
... else:
...     a = li2
...     
>>> a
[1, 2, 3]

^ To długa forma wykonywania takich zadań.

Poniżej znajduje się trójskładnikowa forma. Ale to nie jest najbardziej zwięzły sposób - patrz ostatni przykład.

>>> a = li1 if li1 else li2
>>> 
>>> a
[1, 2, 3]
>>> 

Dzięki Pythonowi możesz po prostu używać ordo alternatywnych zadań.

>>> a = li1 or li2
>>> 
>>> a
[1, 2, 3]
>>> 

Powyższe działa odtąd li1jest, Nonea interpretuje to jako False w wyrażeniach logicznych. Inter interpretuje następnie i ocenia drugie wyrażenie, które nie jest Nonei nie jest pustą listą - więc zostaje przypisane do.

Działa to również z pustymi listami. Na przykład, jeśli chcesz przypisać alistę, która zawiera elementy.

>>> li1 = []
>>> li2 = [1, 2, 3]
>>> 
>>> a = li1 or li2
>>> 
>>> a
[1, 2, 3]
>>> 

Wiedząc o tym, możesz po prostu wykonywać takie zadania za każdym razem, gdy je napotkasz. Działa to również z ciągami znaków i innymi iteracjami. Możesz przypisać adowolny ciąg znaków, który nie jest pusty.

>>> s1 = ''
>>> s2 = 'hello world'
>>> 
>>> a = s1 or s2
>>> 
>>> a
'hello world'
>>> 

Zawsze podobała mi się składnia trójskładnikowa C, ale Python idzie o krok dalej!

Rozumiem, że niektórzy mogą powiedzieć, że nie jest to dobry wybór stylistyczny, ponieważ opiera się na mechanice, która nie jest od razu widoczna dla wszystkich programistów. Ja osobiście nie zgadzam się z tym punktem widzenia. Python jest językiem bogatym w składnię i zawiera wiele idiomatycznych sztuczek, które nie są od razu widoczne dla dablera. Ale im więcej uczysz się i rozumiesz mechanikę bazowego systemu, tym bardziej go doceniasz.

Todd
źródło
1

Inne odpowiedzi poprawnie mówią o trójskładnikowym języku Python. Chciałbym uzupełnić, wymieniając scenariusz, w którym operator trójskładnikowy jest często używany, ale dla którego istnieje lepszy idiom. Jest to scenariusz użycia wartości domyślnej.

Załóżmy, że chcemy użyć option_valuewartości domyślnej, jeśli nie jest ustawiona:

run_algorithm(option_value if option_value is not None else 10)

lub po prostu

run_algorithm(option_value if option_value else 10)

Jednak coraz lepszym rozwiązaniem jest po prostu pisanie

run_algorithm(option_value or 10)
użytkownik118967
źródło
-2

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

wyjdzie

no Input
no Input
no Input
hello
['Hello']
True
ewwink
źródło
1
Chociaż jest przydatny w przypadku podobnych problemów, nie jest to warunek trójskładnikowy. Działa, aby zastąpić x if x else y, ale nie x if z else y.
Perkins,
-2

Świetny sposób na połączenie wielu operatorów:

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
Yaakov Bressler
źródło
-2

Uciążliwa jest domyślna składnia Pythona val = a if cond else b, więc czasami robię to:

iif = lambda (cond, a, b): a if cond else b
# so I can then use it like:
val = iif(cond, a, b)

Oczywiście ma to tę wadę, że zawsze ocenia obie strony (a i b), ale składnia jest dla mnie o wiele bardziej przejrzysta

Baruc Almaguer
źródło
Wydaje się, że jest to dwukrotnie więcej pracy, więcej pamięci RAM i więcej zaciemnienia niż prostsze val = a if cond else bstwierdzenie.
eatsfood
-3
is_spacial=True if gender = "Female" else (True if age >= 65 else False)

**

można go zagnieżdżać według potrzeb. powodzenia

**

To jest Enam
źródło