Soru Python'un üçlü bir koşullu operatörü var mı?


Eğer Python üçlü bir koşullu operatöre sahip değilse, diğer dil yapılarını kullanarak benzetim yapmak mümkün mü?


4442


Menşei


2.5 yaşından büyük Pythons yavaş yavaş tarihe sürükleniyor olsa da, burada eski 2.5 öncesi üçlü operatör hileleri listesi: "Python Deyimler", "Koşullu ifade" metnini arayın . Vikipedi ayrıca oldukça yararlıdır Ж :-) - ジョージ
Yukarıdaki yorumda atıfta bulunulan Python 3.0 resmi belgelerinde, bu "conditional_expressions" olarak adlandırılır ve çok şifreli olarak tanımlanır. Bu belgeler "üçlü" terimini bile içermez, bu yüzden tam olarak neleri arayacağınızı bilmedikçe Google üzerinden bulmak için zorlanırsınız. sürüm 2 belgeleri biraz daha yararlı ve bir bağlantı içerir "PEP 308"Bu soruyla ilgili birçok ilginç tarihsel içerik içerir. - nobar
"üçlü" (üç girdiye sahip olan), bu itirafın sonuçsal bir özelliğidir, kavramın tanımlayıcı bir özelliği değildir. örneğin: SQL case [...] { when ... then ...} [ else ... ] end benzer bir etki için ama hiç üçlü değil. - user313114
ayrıca ISO / IEC 9899 (C programlama dili standardı) bölüm 6.5.15, "koşul operatörü" olarak adlandırır. - user313114
Vikipedi bu makaleyi iyice kapsıyor?:". - HelloGoodbye


Cevaplar:


Evet öyleydi katma 2.5 sürümünde.
Sözdizimi şöyledir:

a if condition else b

İlk condition değerlendirilir, ya sonra a veya b dayalı olarak iade edilir Boole değeri condition
Eğer condition değerlendirir Doğru  a geri döndü, başka b Geri döndü.

Örneğin:

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

Şartların bir ifadedeğil Beyan. Bu, atamaları kullanamayacağınız anlamına gelir veya pass veya koşullu diğer ifadeler:

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

Böyle bir durumda normal kullanmalısın if koşullu ifade yerine.


Birkaç nedenden ötürü bazı Pythonistas tarafından kaşıldığını unutmayın:

  • Argümanların sırası, Python'un "şaşırtıcı" davranışını bilmeyen insanlar tarafından kullanıldığında (siparişi tersine çevirebilirler) hatalara yol açabilecek birçok başka dilden (C, Ruby, Java, vb.) Farklıdır.
  • Bazıları, normal düşüncenin akışına ters düştüğünden, “ilk ve sonra etkileri” düşünerek “kasıtsız” bulurlar.
  • Stilistik nedenler.

Siparişi hatırlamakta sorun yaşıyorsanız, bunu sesli olarak okursanız, (neredeyse) ne demek istediğini söyleyin. Örneğin, x = 4 if b > 8 else 9 yüksek sesle okunur x will be 4 if b is greater than 8 otherwise 9.

Resmi belgeler:


5299



Sipariş kodlayıcılar için garip gelebilir. f(x) = |x| = x if x > 0 else -x Matematikçiler için çok doğal geliyor. Ayrıca, çoğu durumda, C'yi, bunun yerine B'nin yerine B'yi yapması gerektiği dışında da anlayabilirsiniz. - yota
Bunu kullanırken operasyon sırasına dikkat edin. Örneğin, çizgi z = 3 + x if x < y else y. Eğer x=2 ve y=1Bunu 4 elde etmek için bekleyebilirsin, ama aslında 1 verecekti. z = 3 + (x if x > y else y) doğru kullanımdır. - Kal Zekdor
Ek değerlendirmeler yapmak istediğiniz nokta buydu. sonra şartlı değerlendirilir, sonuca bir değer eklemek gibi, her iki tarafa da ek ifadeyi eklemeniz gerekir (z = 3 + x if x < y else 3 + y) veya koşullu grubu (z = 3 + (x if x < y else y) veya z = (x if x < y else y) + 3) - Kal Zekdor
@ Deneme print("OK" if status else "NOT OK") - BusyAnt
Bu sözdizimsel sıralamanın, @yota adında bir kişi tarafından doğal olarak tarif edilen belirsiz ironisini seviyorum. - nickf


Bir tuple indeksleyebilirsiniz:

(falseValue, trueValue)[test]

test geri dönmek gerekiyor Doğru veya Yanlış.
Her zaman uygulamak için daha güvenli olabilir:

(falseValue, trueValue)[test == True]

ya da yerleşik kullanabilirsiniz bool() sağlamak için Boole değeri:

(falseValue, trueValue)[bool(<expression>)]

594



Bu, her zaman her şeyi değerlendirir, oysa if / else yapısı sadece kazanan ifadeyi değerlendirir. - SilverbackNet
(lambda: print("a"), lambda: print("b"))[test==true]() - Dustin Getz
İçinde ne olduğuna dikkat edilmelidir. []s keyfi bir ifade olabilir. Ayrıca, güvenlik için yazarak gerçekliği açıkça test edebilirsiniz [bool(<expression>)]. bool() işlev v2.2.1'den beri olmuştur. - martineau
Bu kod-golf için, gerçek kod için çok fazla değil. Her ne kadar alışkınım olsa da, bazen iki dize sabitleri arasında seçim yapmak gibi belirgin bir şey yaparken, kısırlık için kullanırım. - Claudiu
Benzer bir hile yaptım - sadece bir veya iki kez, ama yaptım - ile bir sözlük içine indeksleme True ve False anahtarlar olarak: {True:trueValue, False:falseValue}[test]  Bunun daha az verimli olup olmadığını bilmiyorum ama en azından "zarif" ve "çirkin" tartışmalardan kaçınıyor. Int'ten ziyade bir boole ile uğraştığınız konusunda bir belirsizlik yoktur. - JDM


2.5'den önceki sürümlerde, hile vardır:

[expression] and [on_true] or [on_false]

Ne zaman yanlış sonuçlar verebilir on_true   yanlış bir boole değeri var.1
Her ne kadar benim görüşüme göre daha açık olan, sağa doğru ifade edilen ifadelerin değerlendirilmesinin faydası vardır.

1. C'nin ”?” Üçlü operatörünün bir karşılığı var mı?


246



Çözüm bu tuzaktan kaçınan (test ve [true_value] veya [false_value]) [0] kullanmaktır. - ThomasH
Üçlü operatör genellikle daha hızlı çalışır (bazen% 10-25). - volcano
@volcano Benim için kaynağın var mı? - OrangeTux
@OrangeTux İşte demonte kod. ThomasH'nin önerdiği yöntemi kullanmak daha da yavaş olacaktır. - mbomb007


deyim1 Eğer şart Başka expression2

>>> a = 1
>>> b = 2
>>> 1 if a > b else -1 
-1
>>> 1 if a > b else -1 if a < b else 0
-1

157



Bu ve en iyi cevap arasındaki fark nedir? - kennytm
Bu, üçlü operatörün birincil amacını vurgular: değer seçimi. Ayrıca, birden fazla üçlüin birlikte tek bir ifadeye zincirlendiğini gösterir. - Roy Tinker
@Craig, Katılıyorum, ancak parantez olmadığında ne olacağını bilmek de yararlıdır. Gerçek kodda, ben de açık parens eklemek eğilimindedir. - Jon Coombs
Her nasılsa, bunu en iyi cevaptan daha iyi anlayabiliyorum. - abhi divekar


itibaren Dökümantasyon:

Koşullu ifadeler (bazen “üçlü operatör” olarak adlandırılır) tüm Python işlemlerinin en düşük önceliğine sahiptir.

İfade x if C else y önce durumu değerlendirir, C (x değil); Eğer C doğru, x değerlendirilir ve değeri iade edilir; aksi takdirde, y değerlendirilir ve değeri döndürülür.

Görmek PEP 308 koşullu ifadeler hakkında daha fazla bilgi için.

2.5 sürümünden beri yeni.


106





Python'da koşullu ifade için bir operatör 2006 yılında bir parçası olarak eklendi Python Geliştirme Önerisi 308. Formu ortakdan farklıdır ?: operatör ve bu:

<expression1> if <condition> else <expression2>

buna eşdeğerdir:

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

İşte bir örnek:

result = x if a > b else y

Kullanılabilecek başka bir sözdizimi (2.5'den önceki sürümlerle uyumlu):

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

işlenenler nerede tembel değerlendirildi.

Başka bir yol, bir tuple indekslemektir (çoğu dilin şartlı operatörü ile tutarlı olmayan):

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

veya açıkça yapılandırılmış sözlük:

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

Başka bir (daha az güvenilir), ancak daha basit bir yöntem kullanmaktır and ve or operatörler:

result = (a > b) and x or y

Ancak eğer bu işe yaramazsa x olabilir False.

Olası bir geçici çözüm yapmaktır. x ve y Listeler veya aşağıdaki gibi tuples:

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

veya:

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

Sözlüklerle çalışıyorsanız, üçlü bir koşul kullanmak yerine, get(key, default), Örneğin:

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

Kaynak: ?: Wikipedia'da Python'da


79





@up:

Ne yazık ki

(falseValue, trueValue)[test]

Çözüm kısa devre davranışına sahip değildir; Böylece hem falseValue hem de trueValue durumdan bağımsız olarak değerlendirilir. Bu, suboptimal veya hatta buggy olabilir (yani hem trueValue hem de falseValue yöntemleri olabilir ve yan etkileri olabilir).

Bunun bir çözümü olurdu

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

(kazanan bilinene kadar yürütme geciktirildi;)), ancak callable ve callable olmayan nesneler arasında tutarsızlık getiriyor. Ek olarak, özellikleri kullanırken durumu çözmez.

Ve öyleyse öykü devam ediyor - bahsedilen 3 çözüm arasında seçim yapmak, kısa devre özelliğine sahip olmak arasında en az python 2.5 (IMHO artık problem değil) kullanarak ve "doğru-değerlendirmeler-yanlış" seçeneğine eğilimli olmamak arasındaki bir alıştırmadır. hatalar.


72





Python 2.5 ve daha yeni bir özel sözdizimi vardır:

[on_true] if [cond] else [on_false]

Eski Pythons'ta üçlü bir operatör uygulanmaz fakat bunu simüle etmek mümkündür.

cond and on_true or on_false

Yine de, potansiyel bir sorun var ki eğer cond değerlendirir True ve on_true değerlendirir False sonra on_false yerine döndü on_true. Bu davranışı istiyorsanız yöntem tamam, aksi takdirde şunu kullanın:

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

tarafından sarılabilir:

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

ve bu şekilde kullanılır:

q(cond, on_true, on_false)

Tüm Python sürümleriyle uyumludur.


48



Davranış aynı değil - q("blob", on_true, on_false) döner on_false, buna karşılık on_true if cond else on_false döner on_true. Bir geçici çözümün yerini alması cond ile cond is not None Bu durumlarda, bu mükemmel bir çözüm olmasa da.
Neden olmasın bool(cond) yerine cond is True? Eski, gerçekliği kontrol eder cond, ikincisi ile işaretçi eşitliği kontrol eder. True nesne. @AndrewCecil tarafından vurgulandığı gibi, "blob" gerçektir ama is not True. - Jonas Kölker
Vay, bu gerçekten hacky görünüyor! :) Teknik olarak bile yazabilirsiniz [on_false, on_True][cond is True] böylece ifade kısalıyor. - Arseny


Farklı programlama dillerinde üçlü operatör

Burada sadece bazı önemli farklılıkları göstermeye çalışıyorum. ternary operator Birkaç programlama dili arasında.

Javascript'te Üçlü Operatör

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

Ruby'de Üçlü Operatör

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

Scala'da Üçlü operatör

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

R programlamada üçlü operatör

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

Python'da Üçlü operatör

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

Şimdi python dilinin güzelliğini görebilirsiniz. Son derece okunabilir ve bakımı yapılabilir.


39



Bu Blogger, python'un üçlü operatörünün diğer birçok dilden gereksiz şekilde farklı olduğunu tespit etti. - JamesThomasMoon1979
Ruby ayrıca ile çalışır a = true ? 1 : 0 - rneves
"Şimdi python dilinin güzelliğini görebilirsiniz. Son derece okunabilir ve sürdürülebilir." Bu cümlenin alaka düzeyini, üçüncül operatör söz diziminin bunu nasıl gösterdiğini göremiyorum. - DaveMongoose
Kanaatli olabilir; ama aslında söylediği şey, Python sözdiziminin, üç yüzlü bir operatörün hiç görmediği bir kişi tarafından anlaşılmasının muhtemel olması iken, çok az insan, ilk olarak ne anlama geldiği söylenmedikçe daha genel sözdizimini anlayacaktır. - fralau
Algol68: a = .if. .doğru. .sonra. 1. 0fi. Bu da bir = (. Doğru. | 1 | 0) olarak ifade edilebilir. Her zamanki gibi Algol68, halefleri üzerinde bir gelişmedir. - Albert van der Horst


Sık sık bulabilirsiniz

cond and on_true or on_false

ancak bu, on_true == 0 olduğunda sorun oluşturuyor

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

Normal bir üçlü operatör için beklediğiniz bu sonuç

>>> x = 0
>>> print 0 if x == 0 else 1 
0
>>> x = 1
>>> print 0 if x == 0 else 1 
1

31





Kesinlikle, ve anlamak inanılmaz derecede kolay.

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

27



Projeniz çizgi genişliğini sınırlarsa, aslında kullanımı kolay değildir. :( - weberc2