Soru ya da elif ya doğruysa o zaman bir şey yap


Bu sadece akademik ilgi içindir. Aşağıdaki durumla çok karşılaşıyorum.

either_true = False
if x:
  ...do something1
  either_true = True
elif y:
  ...do something2
  either_true = True
if either_true:
  ..do something3

Bunu yapmanın pythonik bir yolu var mı, yoksa genel olarak daha iyi bir programlama tarzı var. Temelde bir şey yapar3 sadece elif doğruysa yürütür.


44
2018-02-13 14:04


Menşei


Mevcut çözümün optimal gibi görünüyor. ChrisProsser'in cevabı gibi diğer yaklaşımlar değerlendirmeyi gerektirir x ve / veya y birden fazla. - Frédéric Hamidi
Bir işle3 bir şey koyun ve her iki daldan da adlandırın. - RemcoGerlich
Bu başbakan olur if...else...finally, çok da kötü değil. - wnnmaw
@wnnmaw - Ben katılmıyorum. Beklemek isterim finally ne olursa olsun yürütmek - cümlelerden sadece biri doğru değilse, ish. - mgilson
Bunun gibi bir kodum vardı, ama if..elif ile eğer arasında bir şeyler vardı, bu durumda gerçekten bunun en iyi çözüm olduğunu düşünüyorum. - Cruncher


Cevaplar:


Kodun neredeyse Kod tekrarı ve değerlendirmesi söz konusu olduğunda, optimaldir. Tekrarı önlemek için düşünebildiğim tek şey:

# be optimistic!
either_true = True
if x:
    do_something1
elif y:
    do_something2
else:
    either_true = False

if either_true:
    do_something3

Bu, toplam satır sayısı değişmese de, bir atamayı kaldırır.

Bunun avantajı, bununla birlikte çalışmasıdır. n Mevcut bir çözüm gerektirirken, başka bir görev eklemeden koşullar either_true = True her koşul için.

Benim düşünceme göre aynı derecede okunabilirliğe sahipler, ancak yukarıdaki kod daha fazla koşulla daha iyi olacak.

Ayrıca, kod tekrarını önleyen ve verimlilik açısından optimal olan okunabilir bir çözüm de olmayan "pythonic" bir yol yoktur ve aynı sonucu elde etmek için herhangi bir "daha iyi programlama" bilmiyorum.


31
2018-02-13 20:14



Bu kesinlikle akıllıca konsepti geliştirir - user1572215
Bu açıkça en iyi cevaptır. - KRyan
Bu, belirli bir soru için iyi bir cevaptır, ancak eğer ya_true'nin yanlış olması gerektiği başka bir 'elif' olsaydı, bu çok faydalı olmazdı. Asıl soru 'akademik ilgi' idi, bu yüzden sadece bir elif ifadesiyle sınırlı olması muhtemel değil. - Alex
@Alex Aslında, sadece either_true=False olması gereken her dalda False. Kullanabileceğiniz şube sayısına bağlı olarak True veya False Ödev sayısını en aza indirmek için varsayılan olarak. Cevabımda açıkça belirttiğim gibi, eğer sahip olduğun durumda genelleme yaparsak n koşulları ve eğer değişkenin doğru olmasını istiyorsanız herhangi bunlardan doğrudur, o zaman cevabımdaki kod en uygun çözümdür. Ayrıca diğer cevapların bunu nasıl hesaba kattığını göremiyorum. - Bakuriu
Bunun bir dezavantajı, ilgili koddur (ör. do_something1 bunu takiben do_something3) düzinelerce satır olabilir, kodu okurken aşağı atlamak zorundasınız. Sadece tekrar etmek istemediğin için do_something3 - ve tekrar etmekten kaçınmak için çok fazla çaba göstermenin nedeni, kesinlikle tek bir işlev çağrısından daha fazlası olmasıdır. Bir devlet parçası ekleme either_true) değişkeni problemin bir çözümü gibi görünüyor do_something3 olması gereken yerde doğru tekrar yapmak için çok fazla kod (sağ altında) do_something1örneğin, uygulanabilir. - Frerich Raabe


Ayrıca ihmal edebilirsiniz either_true eğer tamamen bayrak doSomething3 tek bir kod satırıdır (ör. bir işlev çağrısı):

if x:
  ..do something 1
  ..do something 3
elif y:
  ..do something 2
  ..do something 3

Değerlendirmenin güzel özelliğini korur x ve y en çok bir kere (ve y eğer değerlendirilmezse x doğru).


35
2018-02-13 14:12



Harika. 1 satır kod tekrarlamak için tamam ... - glglgl
Eğer do something 3 bir işlev çağrısı, sonra evet, bu harika. Bunu boolean yaklaşımı üzerinden alırdım. - 2rs2ts
ve eğer bir işlev çağrısı değilse, muhtemelen bir taneye dönüştürülebilir. - RemcoGerlich
@ZanLynx Boolean ile ayarlamak için hatırlamak zorunda either_true = Trueve iç içe geçmiş ifadelerle eklemeleri gerektiğini hatırlamak zorundalar z iki yerde. Üçüncü (veya daha fazla) bir vaka eklendiğinde bir şeyin eklenmesi gereken bir şey kaçınılmazdır, ancak bu IMO en sürdürülebilir olanıdır. - Izkata
@Thedayturns sanırım yeterince açık değildi: IMHO en iyi düzeltme kodu ne olursa olsun taşımaktır doSomething3 ayrı bir işleve aittir. Bu (@ kullanıcı1572215'in doğru bir şekilde işaret ettiği gibi) da soruna engel olur. - Frerich Raabe


Bunu iç içe geçmiş ifadeleri kullanarak ele alırım.

if x or y:
    if x:
        ...do something1
    elif y:
        ...do something2
    ...do something3

Bazı yorumların işaret ettiği gibi, en iyi çözüm x & y'nin ne olduğuna bağlı olacaktır. Eğer kolay okunabilirlik / özlü kod sizin hedefinizse, bu veya verilen diğer cevaplar iyi olmalıdır. Eğer x & y, pahalı fonksiyon çağrıları ise, o zaman, fonksiyonu iki kez çağırmaktan kaçınmak için yaptığınız gibi bir şey yapmak daha iyi olacaktır.


19
2018-02-13 14:07



mmm ... eğer x ve y basit ifadeler, sonra evet. Aksi halde hayır. - glglgl
@Christian Basit ifadeler değilse, e. g. Bir işlev çağrısı içerir, çağrı iki kez yapılır, hangi istenen şey olmayabilir. - glglgl
@Christian, x olabilirdi compare_thousands_of_matrices() ve y olabilirdi check_slow_server_response(), Örneğin. - Frédéric Hamidi
Sonucu (işlev tarafından döndürülen değer) değişkenlere atayabilirsiniz x ve yYani, herhangi bir işlev sadece bir kez değerlendirilir. - Christian
Bu durumda "elif y:", "else:" ile değiştirilebilir. - Kundor


Bazılarını bir işlevde sarabilirsiniz:

def do_stuff():
    if x:
        ...do something1
        return True
    elif y:
        ...do something2
        return True
    else:
        return False

if do_stuff():
    ..do something3

Ya da hepsi bir işlevde:

def do_stuff()
    if x:
        ...do something1
    elif y:
        ...do something2
    else:
        return

    ..do something3

7
2018-02-13 14:11



Ayrıca önerebilirsiniz bunun gibi, silinen cevabımı görüntüle. - Grijesh Chauhan
@GrijeshChauhan: Bu durumda iade değerinin anlamını haklı çıkarmak zor olsa da - Eric
evet Cevabımı bir dakika içinde sildim. İlk başta kafa karıştırıcıdır ve bazı programcılar yoda-notasyonları gibi sevmezler. Ama yine de paylaşmak istediğim için paylaştım. - Grijesh Chauhan


Önceden önerilenlere tamamen farklı bir çözüm sunma ruhunda, önceden tanımlanmış "bazı şeylere" bağlı birden fazla vaka oluşturmanıza izin veren bir liste yapılandırılmış sözlükler oluşturabilirsiniz.

cases = [
    {'condition' : x, 'action' : something1},
    {'condition' : not x and y, 'action' : something2},
    {'condition' : x or y, 'action' : something3},
]

for c in cases:
    if c['condition']: c['action']

Aslında bu yöntemi gerçekten çok seviyorum (ve sadece bu soruya eşsiz bir cevap bulmaya çalışırken bunu keşfettim, teşekkürler!) - Hangi davaya hangi eylemin bağlı olduğu ve birkaç tane daha eklemek çok kolay. / else ifadeleri eklemeden durumlar.


6
2018-02-13 17:45



ChrisProsser'ın cevabı gibi aynı problem - eğer bu çalışırsa x ve y basittir, ancak aslında pahalı fonksiyon çağrıları varsa, bunları önce değişkenlere ayırmanız gerekir, böylece birden çok kez çağrılmazlar. Ve o zaman bile, herşey Bu koşulların kaçması, istemeyebilir. - Izkata
Mükemmel nitelikler Izkata! - Quentin Donnellan
Make kullanırsanız cases Koşullar ve eşleşen kodu uygulayan fonksiyonlar için tuples demetleme (lambda) fonksiyonlarının bir listesi, gerçek döngüyü sadece results = [action() for (condition, action) in cases if condition(x,y)]. Kodu bu veriye dönüştürmek için bu yaklaşımın güzel bir yönü, vaka sayısını saymak veya kayıtlı koşulları veya benzerlerini sıralamak gibi şeyleri kolayca yapabileceğinizdir. Bu, komut yorumlayıcıları için iyi çalışır (özel komutlarla genişletilebilen IRC istemcileri düşünün). - Frerich Raabe


if x or y:
    dosomethig1() if x else dosomething2()
    dosomething3()

Tabii ki bu değerlendiriyor x.__nonzero__ iki defa. Genelde bu büyük bir anlaşma değil, ancak pahalıysa, her zaman bunu önceden değerlendirebilir ve geçici bir değişkene kaydedebilirsiniz.


5
2018-02-13 14:08



Eğer x and y, dosomething2() yur çözümü ile atlandı. - glglgl
Eğer başka bir yapıya katılmıyorum. X değil demek y. - Theox
@glglgl - Evet, biliyorum. OP'lerde de atlandı. - mgilson
@Theox - Bu durumda, evet öyle çünkü if x or y fıkra. Bunlardan biri doğru olmalı (ish). Eğer değilse xsonra y - mgilson
@mgilson Ouch, tamam. Ben atladım elif: Bölüm... - glglgl


Bu önerilerin tamamı ile birlikte geldiğiniz diğer kişiler için, şunu unutmayın: x ve y pahalı ifadelerdir:

if askTheServer() or readTheOneGigabyteConfigFile():
   ...

İlk önce bu ifadelerin hızlı değerlendirme değerlerine dönme değerlerini atayabilirsiniz:

x = askTheServer()
y = readTheOneGigabyteConfigFile()
if x or y :
   ...

4
2018-02-14 00:37





either_true = x or y
if x:
  ...do something1
elif y:
  ...do something2
if either_true:
  ..do something3

2
2018-02-13 14:14



Her ikisi de x or y ve any([x, y]) bool olmayanlarla bile aynı anlama gelir. - glglgl
Oops, haklısın. Bu yorumdan kurtuldum. - Jae


Ben bir şeyler yapardım .. bazı şeyleri işler ve bir tane elif yazarım:

def do_x():
  .. do something 1
  .. do something 3

def do_y():
  .. do something 2
  .. do something 3

if x:
   do_x()
elif y:
   do_y()

Bu güzel .. eğer bazı şeyler bir sürü şey içeriyorsa.


2
2018-02-13 23:17





Eğer bir şey yapmak oldukça kısasa, (1), do (2) ya da bunun gibi bir şey gibi, bunu şöyle yapabilirsin:

(x and (do(1), x) or y and (do(2), y)) and do(3)

0
2018-02-21 06:57