'İf' ifadelerinde çok satırlı koşullar oluşturuluyor mu? [kapalı]


677

Bazen uzun koşulları ifbirkaç çizgiye bölerim. Bunu yapmanın en belirgin yolu:

  if (cond1 == 'val1' and cond2 == 'val2' and
      cond3 == 'val3' and cond4 == 'val4'):
      do_something

Görsel olarak çok çekici değil, çünkü eylem koşullarla karışıyor. Bununla birlikte, 4 boşluğun doğru Python girintisini kullanmanın doğal yoludur.

Şu an için kullanıyorum:

  if (    cond1 == 'val1' and cond2 == 'val2' and
          cond3 == 'val3' and cond4 == 'val4'):
      do_something

Ama bu çok hoş değil. :-)

Alternatif bir yol önerebilir misiniz?


2
Editörünüz pep8 kullanıyorsa PEP8 ihlallerini ne zaman uyarmanız gerektiğini tespit etmek Python paketini E125 hatasını devre dışı bırakmanız veya pep8paketin ölçütlerini karşılayan bir biçimlendirme çözümü bulmanız gerekir . pep8Paketin sorunu # 126 kesinlikle PEP8 teknik özelliğinin izlenmesinin paketi sabitleme hakkındadır. Konu ile ilgili tartışma burada da görülen bazı stil önerilerini içermektedir.
akaihola

1
İlk örnek için pep8'in "E129 görsel olarak girintili çizgiyi bir sonraki mantıksal çizgiyle aynı girintili" atacağını unutmayın.
Taylor Edmiston

Bu soru çok eskidir ve bir ton görüşe sahiptir, ancak kesin olarak görüşe dayanmaktadır. "Çok çekici değil" ve "çok hoş değil" dili, sözde doğru cevabın, soru soranların estetik tercihiyle (yani bir görüşle) en iyi uyuştuğu kriter olduğunu ortaya koyuyor. Tam olarak aynı soruyu sorabilirim ve bunun bir kopya olmadığını iddia edebilirim çünkü estetik zevkim onu ​​farklı olarak nitelendirir ve farklı bir "doğru" cevaba yol açacaktır.
Z4 katmanlı

@ Z4-katmanı: evet, görüşe dayalı. Ama 12 yıl önce istendi. SO o zamanlar farklı, nazik bir yerdi. Son zamanlarda, SO standartları değiştiği için downvotes biriktiriyor. Yine de, 1 milyondan fazla kez incelendiğinde, umarım dünyada zarardan daha iyidir. Bugün aynı soruyu merak edenleri görüyorum, Google'ı araştırıyor, bu tartışmaya iniyor ve düşünmelerini kalibre etmeyi faydalı buluyorum. Aralarından seçim yapabileceğiniz birçok yüksek oyu var.
Eli Bendersky

@EliBendersky tamamen katılıyorum. SO'nun devam eden bir kimlik krizine sahip olduğu gibi: "kurallara" açıkça uymasa da (geçerli cevapların sayısı bunun bir kanıtıdır), değer kattığı açıktır. Her şey eşit olduğunda, görüşleri benimkinden farklı olsa bile, kodlama stili hakkında açık ve mantıklı görüşler geliştiren biriyle çalışmayı tercih ederim.
Z4 katmanı

Yanıtlar:


750

İkinci koşullu satırınızda 4 boşluk kullanmanıza gerek yoktur. Belki kullanın:

if (cond1 == 'val1' and cond2 == 'val2' and 
       cond3 == 'val3' and cond4 == 'val4'):
    do_something

Ayrıca, beyaz alanın düşündüğünüzden daha esnek olduğunu unutmayın:

if (   
       cond1 == 'val1' and cond2 == 'val2' and 
       cond3 == 'val3' and cond4 == 'val4'
   ):
    do_something
if    (cond1 == 'val1' and cond2 == 'val2' and 
       cond3 == 'val3' and cond4 == 'val4'):
    do_something

Her ikisi de oldukça çirkin.

Belki köşeli parantezlerini kaybedebilirsiniz ( Stil Kılavuzu bunu engelliyor)?

if cond1 == 'val1' and cond2 == 'val2' and \
   cond3 == 'val3' and cond4 == 'val4':
    do_something

Bu en azından size biraz farklılaşma sağlıyor.

Ya da:

if cond1 == 'val1' and cond2 == 'val2' and \
                       cond3 == 'val3' and \
                       cond4 == 'val4':
    do_something

Bence tercih ederim:

if cond1 == 'val1' and \
   cond2 == 'val2' and \
   cond3 == 'val3' and \
   cond4 == 'val4':
    do_something

İşte (2010'dan beri) parantez kullanılmasını öneren Stil Kılavuzu .


45
Sondaki \ çözümlerin PEP 8 tarafından önerilmediğini unutmayın. Bunun bir nedeni, bir \ 'den sonra yanlışlıkla boşluk eklenmesi, editöründe gösterilmeyebilmesi ve kodun sözdizimsel olarak yanlış hale gelmesidir.
Eric O Lebigot

14
Bu yanlıştır, stil kılavuzu, "Uzun satırlar, parantez içine ifadeler sarılarak birden çok satıra kesilebilir. Bunlar, satır devamında ters eğik çizgi kullanılmasına tercih edilmelidir." Bunu burada görebilirsiniz: python.org/dev/peps/pep-0008/#maximum-line-length
joshcartme

8
@joshcartme PEP, ters eğik çizgileri açıkça reddetmek için hg.python.org/peps/rev/7a48207aaab6 adresinde değişti . Cevabı güncelleyeceğim.
Harley Holcombe

3
Teşekkürler, şimdi önerilmedikleri için örneklerinizi de güncellemek iyi bir fikir olabilir. Bunu kendim anlamaya çalışıyordum ve cevabınız ile stil rehberi (dolayısıyla benim yorumum) arasındaki tutarsızlıktan şaşkındım. Ben sadece bilgiçlik yapmaya çalışmıyordum.
joshcartme

3
PEP 8 şimdi andve sonrasında da kırılmayı caydırıyorif .
virtualxtc

124

Ben sadece AND veya OR's olduğu dejenere durumda aşağıdakilere başvurdum.

if all( [cond1 == 'val1', cond2 == 'val2', cond3 == 'val3', cond4 == 'val4'] ):

if any( [cond1 == 'val1', cond2 == 'val2', cond3 == 'val3', cond4 == 'val4'] ):

Birkaç karakteri tıraş eder ve koşulun incelikli olmadığını netleştirir.


4
Bu ilginç bir yaklaşım. Yine de uzun koşullar konusuna
değinmiyor

20
Kısa dolaşımı önemsemiyorsanız sorun değil.
Constantin

63
kısa süreli eğitim her zaman hızlı değildir. İyi uygulamaların kodlama olmasa da, böyle bir kod mevcut olabilir: if destroy_world and DestroyTheWorld() == world_is_destroyed: .... Harika, şimdi kazayla dünyayı yok ettin. NASIL YAPABİLDİN?
Aaron

4
Bunun çok fazla oyu olduğuna şaşırdım. Bu cevap, çok satırlı koşulların şekillendirilmesiyle ilgili orijinal soruyu tamamen yok sayar .
Przemek D

2
Bu ifade tembel değil. Bu nedenle, bazı koruma koşullarının ardından muhtemelen başarısız olan bir durum izleniyorsa, eşdeğer değildir.
eugene-parlak

57

Birisi burada dikey boşluk kullanımını savunmak zorunda! :)

if (     cond1 == val1
     and cond2 == val2
     and cond3 == val3
   ):
    do_stuff()

Bu, her koşulu açıkça görünür kılar. Ayrıca daha karmaşık koşulların daha temiz ifadesine izin verir:

if (    cond1 == val1
     or 
        (     cond2_1 == val2_1
          and cond2_2 >= val2_2
          and cond2_3 != bad2_3
        )
   ):
    do_more_stuff()

Evet, anlaşılır olması için biraz dikey emlak ticareti yapıyoruz. Buna değer IMO.


19
Bu ne güzel ne de PEP8 uyumlu değil. PEP8, ikili bir operatörün (örneğin andyanı sıra or) etrafını kırmak için tercih edilen yerin , operatörden önce değil, operatörden sonra olduğunu söylüyor.
Chris Medrela

7
@ChristopherMedrela arkasındaki mantığı anlatıyor mu? mantık operatörü önce bir satır sonu yerleştirmek çok daha net olduğunu düşünüyorum
Norill Tempest

4
Operatörü ilk sıraya koymak düğüm dünyasında oldukça yaygındır. Bunun mantığı, soldaki şeyleri sağdaki şeylerden çok daha hızlı fark etmemiz ve okumamızdır - en azından batı kültürlerinde. Unutulmuş bir virgülün sessiz hatalara neden olabileceği JavaScript'te çok geçerlidir.
tomekwi

11
Bunu yapma lütfen. Sadece PEP8zincirleme değil, aynı zamanda zincirleme yaptığınız mantıksal işlemi belirlemeyi de zorlaştırıyor. Kod inceleme yoluyla masamıza geldi, ben bu flunk.
Urda

11
PEP8'in mevcut sürümünden itibaren, ikili bir operatörden önce veya sonra kopma kabul edilebilir ve operatör yeni kod için daha iyi kabul edilir.
Soren Bjornstad

31

Çok büyük bir if-koşulum olduğunda bu stili tercih ederim:

if (
    expr1
    and (expr2 or expr3)
    and hasattr(thingy1, '__eq__')
    or status=="HappyTimes"
):
    do_stuff()
else:
    do_other_stuff()

2
Girintileri izleyebileceğiniz yerlerde tutmak için +1. Python'u seviyorum ve çok kullanıyorum, ama sürekli girintili olmaya zorlandığım için sürekli rahatsız oluyorum. Çok hatlı, iyi yapıldığında bile estetiği gerçekten yok ederse.
mightypile

4
Hattınızın başında andve oroperatörlerinizin PEP 0008'i ihlal ettiğini ve "İkili bir operatörün etrafında kırmak için tercih edilen yer, operatörden önce değil, ondan önce" olduğunu belirtir . . Eğer if koşulunu vücuttan ayırmak için kendi hattında kapatma braketine ve kolonuna sahip olmayı seviyorum (ve bunu Boole operatörlerini PEP-0008 uyumluluğu için hattın sonunda tutarken yapmak mümkündür).
Mark Amery

8
2016 itibariyle: For decades the recommended style was to break after binary operators. But this can hurt readability in two ways... In Python code, it is permissible to break before or after a binary operator, as long as the convention is consistent locally. For new code Knuth's style is suggested.(Knuth'un stili operatörle çizgiyi başlatmaktır).
cowbert

27

İşte benim kişisel kişisel bakışım: uzun koşullar (benim görüşüme göre), bir boole döndüren işlev / yönteme yeniden düzenleme öneren bir kod kokusudur. Örneğin:

def is_action__required(...):
    return (cond1 == 'val1' and cond2 == 'val2'
            and cond3 == 'val3' and cond4 == 'val4')

Şimdi, çok hatlı koşulları iyi göstermenin bir yolunu bulsaydım, muhtemelen kendime sahip olmaktan memnun olurdum ve yeniden düzenlemeyi atlarım.

Öte yandan, estetik anlayışımı bozmalarını sağlamak, yeniden düzenleme için bir teşvik görevi görür.

Sonuç olarak, birden fazla çizgi koşulunun çirkin görünmesi gerektiği ve bu durum onları önlemek için bir teşviktir.


23

Bu pek gelişmiyor ama ...

allCondsAreOK = (cond1 == 'val1' and cond2 == 'val2' and
                 cond3 == 'val3' and cond4 == 'val4')

if allCondsAreOK:
   do_something

1
İlginç bir alternatif. Ama 2 ekstra satır :-)
Eli Bendersky

Gerçekten yinelemeli bir döngüde iyi çalışmaz, bir şey yapan işlevlerle çalışmaz ... ve adil olmak - çirkin
Mez

9
brian, kısmen katılmıyorum. Bir hesaplamanın ara sonuçları için değişkenlerin kullanılması kodun anlaşılmasını kolaylaştırabilir ve derlenmiş bir dilde herhangi bir performans etkisi olmaz. Muhtemelen python'da olurdu, ama eğer performans o kadar önemli olsaydı python kullanmazdım.
Mark Baker

1
@ MarkBaker Martin Fowlers "Refactoring" i okuyana kadar yazdıklarına katılırdım. Bu tür ara değişkenlerin faydadan çok zarara neden olduğu konusunda mükemmel bir argüman sunmaktadır. Sonraki yeniden düzenlemeyi engellerler. Bunlar olmadan yapmak, daha işlevsel bir programlama stiline yol açar, bu da kendini yeniden düzenlemeye iyi verir. Bu beni şaşırttı, ama haklı olduğuna inanıyorum ve o zamandan beri böyle gereksiz ara maddeleri kodumdan elimine etmeye çalıştık - birden fazla kullanılsalar bile.
Jonathan Hartley

2
Güzel, ama neden camelCase ?! :)
Leonid Shvechikov

19

andAnahtar kelimeyi ikinci satıra taşımanızı ve dört yerine iki boşluk içeren koşulları içeren tüm satırlara girintiyi öneririm :

if (cond1 == 'val1' and cond2 == 'val2'
  and cond3 == 'val3' and cond4 == 'val4'):
    do_something

Kodumda bu sorunu tam olarak nasıl çözdüğüm budur. Satırdaki ilk kelime olarak bir anahtar kelimeye sahip olmak, koşulu çok daha okunabilir hale getirir ve boşluk sayısını azaltmak koşulu eylemden daha da ayırır.


9
Gries veya Djikstra'da mantık operatörünü çizginin önüne koymanın - daha görünür hale getirmenin - yardımcı olduğunu bir yerde okudum. Ve bunu 90'lı yıllardan beri yapıyorum. Ve yardımcı olur.
S.Lott

7
Stil Kılavuzu'nun koşulun satırın sonuna yerleştirilmesini önerdiğini unutmayın.
Harley Holcombe

3
Bu konuda hiçbir zaman hemfikir olmama rağmen bu doğru. Ne de olsa sadece bir rehber.
DzinX

8
PEP8 artık koşulun satır sonuna yerleştirilmesini önermemektedir .
Soren Bjornstad

14

Bu konuyu mütevazi bir uzunlukta yorumladığı için PEP 0008'den (Python'un resmi stil rehberi) alıntı yapmaya değer görünüyor :

Bir durumun koşullu kısmı, ifbirden çok satırda yazılmasını gerektirecek kadar uzun olduğunda, iki karakterlik bir anahtar kelimenin (yani if), artı tek bir boşluğun ve bir açılış parantezinin doğal bir 4- çok satırlı koşullu izleyen satırlar için boşluk girintisi. Bu, ifdoğal olarak 4 boşluğa girintilenecek olan -statement içine yerleştirilmiş girintili kod takımıyla görsel bir çatışma oluşturabilir . Bu PEP, bu koşullu çizgilerin if-statement içindeki yuvalanmış süitten görsel olarak nasıl ayırt edileceği (veya edilip edilmeyeceği) konusunda açık bir pozisyon almaz. Bu durumda kabul edilebilir seçenekler aşağıdakileri içerir, ancak bunlarla sınırlı değildir:

# No extra indentation.
if (this_is_one_thing and
    that_is_another_thing):
    do_something()

# Add a comment, which will provide some distinction in editors
# supporting syntax highlighting.
if (this_is_one_thing and
    that_is_another_thing):
    # Since both conditions are true, we can frobnicate.
    do_something()

# Add some extra indentation on the conditional continuation line.
if (this_is_one_thing
        and that_is_another_thing):
    do_something()

Yukarıdaki alıntıda "sınırlı değil" ifadesine dikkat edin; stil rehberinde önerilen yaklaşımların yanı sıra, bu sorunun diğer cevaplarında önerilenlerden bazıları da kabul edilebilir.


PEP8 için +1. Bu gerektiğini bunun (pratikte konuşma) olduğundan, resmi Python stil kılavuzuna kabul edilecek.
Michael - Clay Shirky

2
Ayrıca, PEP8, bu PEP'in bu koşullu çizgileri if -statement içindeki yuvalanmış süitten nasıl görsel olarak ayırt edip etmeyeceği (veya edip etmeyeceği) konusunda açık bir pozisyon almadığından açıkça belirtmektedir. Bu durumda kabul edilebilir seçenekler şunları içerir, ancak bunlarla sınırlı değildir: ... (kesilmiş) Yani, tartışmayı bırak, beğendiğin bir şeyle git!
RayLuo

7

İşte yaptığım şey, "tüm" ve "herhangi bir" öğelerinin yinelemeyi kabul ettiğini unutmayın, bu yüzden bir listeye uzun bir koşul koydum ve "tüm" ün işi yapmasına izin verdim.

condition = [cond1 == 'val1', cond2 == 'val2', cond3 == 'val3', cond4 == 'val4']

if all(condition):
   do_something

4

Tercih ettiğim çözümü görmemeye şaşırdım,

if (cond1 == 'val1' and cond2 == 'val2'
    and cond3 == 'val3' and cond4 == 'val4'):
    do_something

Yana andbir anahtar kelimedir, benim editör tarafından vurgulanan ve onun altındaki do_something yeterince farklı görünüyor alır.


Ancak devam çizgisi hala bir sonraki mantıksal çizgiden kendini
ayırmıyor

1
Bunun bir PEP 0008 ihlali olduğuna dikkat edin ( "İkili bir operatörün çevresinde kırmak için tercih edilen yer, operatörden önce, ondan önce değil" ). Umursadığınız, elbette, size kalmış.
Mark Amery

1
Bu arada, bu benim tercih ettiğim çözüm değil. ;)
Marius Gedminas

4

@Krawyoti'nin söylediklerine ek olarak ... Uzun koşullar kokuyor çünkü okunması zor ve anlaşılması zor. Bir işlev veya değişken kullanmak kodu daha net hale getirir. Python'da, dikey boşluk kullanmayı, parantez içine almayı ve mantıksal işleçleri her satırın başına yerleştirmeyi tercih ederim, böylece ifadeler "yüzen" gibi görünmez.

conditions_met = (
    cond1 == 'val1' 
    and cond2 == 'val2' 
    and cond3 == 'val3' 
    and cond4 == 'val4'
    )
if conditions_met:
    do_something

Koşulların bir whiledöngüde olduğu gibi birden fazla değerlendirilmesi gerekiyorsa , yerel bir işlev kullanmak en iyisidir.


1
Buna ek olarak, ekstra değişken oluşturmak yerine gerçek yanlışınızı döndürmek için bir işlev veya lambda bildirebilirsiniz.
Techdragon

Eğer koşullar başka bir yerde olacaksa @Techdragon, bir lambda bloğuna koymak lambda bloğunun isimlendirilmesini gerektirir, böylece if durumunda daha sonra başvurulabilir. Eğer bir lambda isimlendirilecekse, neden normal bir fonksiyon değil de? Ben şahsen bu azaltılmış boole ifadesini seviyorum.
Sri Kadimisetty

Kabul ediyorum, bu yüzden normalde çoğu durumda program kontrol akışını anlamak için kayma sırasında geliştirilmiş okunabilirlik ve zihinsel sindirim kolaylığı için bir işlev kullanacağım. İnsanların özellikle alan bilincinde olması durumunda 'daha küçük' seçeneğin de mevcut olduğundan emin olmak için lambda'dan bahsediyorum.
Techdragon

4

Şahsen, uzun if ifadelerine anlam katmayı seviyorum. Uygun bir örnek bulmak için kod aramak zorunda kalacak, ama akla gelen ilk örnek: diyelim ki birçok değişkene bağlı olarak belirli bir sayfayı görüntülemek istediğim bazı ilginç mantıkla karşılaşıyorum.

Türkçe: "Oturum açmış olan kullanıcı yönetici öğretmen DEĞİL, sadece normal bir öğretmense ve öğrencinin kendisi değilse ..."

if not user.isAdmin() and user.isTeacher() and not user.isStudent():
    doSomething()

Elbette bu iyi görünebilir, ancak ifadeleri okumak çok iş ise. Mantıklı olan etikete mantığı atamaya ne dersin. "Etiket" aslında değişken adıdır:

displayTeacherPanel = not user.isAdmin() and user.isTeacher() and not user.isStudent()
if displayTeacherPanel:
    showTeacherPanel()

Bu aptalca görünebilir, ancak SADECE başka bir öğeyi görüntülemek istediğiniz başka bir koşulunuz olabilir ve yalnızca öğretmen panelini görüntülüyorsanız VEYA kullanıcı varsayılan olarak diğer belirli panele erişimi varsa:

if displayTeacherPanel or user.canSeeSpecialPanel():
    showSpecialPanel()

Yukarıdaki koşulu mantığınızı saklamak ve etiketlemek için değişkenler kullanmadan yazmayı deneyin ve sadece çok dağınık, okunması zor bir mantıksal ifade ile değil, aynı zamanda kendinizi tekrarladınız. Makul istisnalar olsa da unutmayın: Kendinizi Tekrarlamayın (KURU).


3

"all" ve "any" ifadeleri, aynı türden birçok durum için uygundur. AMA her zaman tüm koşulları değerlendirir. Bu örnekte gösterildiği gibi:

def c1():
    print " Executed c1"
    return False
def c2():
    print " Executed c2"
    return False


print "simple and (aborts early!)"
if c1() and c2():
    pass

print

print "all (executes all :( )"
if all((c1(),c2())):
    pass

print

5
Yanlış! Onlar sadece sizin yaptığınız için yapar. [C1, c2] içindeki f için tümünü (f () deneyin).
habnabit

2
İşlevleri sadece örnek olarak kullandığını düşünüyorum, çünkü kolayca bir şeyler yazdırmasını sağlayabilir. Bir listede verilen bir dizi rasgele ifadeyi düşünürsek all(), her birini bir lambdaya sarıp hilenizi kullanmazsanız f(), hepsi değerlendirilecektir. Başka bir deyişle, Aaron: Sanırım Anders, callables'ı belirli bir örnek olarak kullanarak genel koşullar hakkında konuşmaya çalışıyordu; ancak tepkiniz yalnızca işlevler için geçerlidir.
Brandon Rhodes

3

(Sabit genişlikli adlar gerçek kodu temsil etmediği için hafifçe değiştirdim - en azından karşılaştığım gerçek kodu değil - ve bir örneğin okunabilirliğini taşıyacak.)

if (cond1 == "val1" and cond22 == "val2"
and cond333 == "val3" and cond4444 == "val4"):
    do_something

Bu, "ve" ve "veya" (ilk önce ikinci satırda olmaları önemlidir), ancak diğer uzun koşullar için çok daha az işe yarar. Neyse ki, birincisi daha sık görülen bir durum gibi görünüyor, ikincisi genellikle geçici bir değişkenle kolayca yeniden yazılıyor. (Genellikle zor değildir, ancak yeniden yazarken "ve" / "veya" kısa devresini korumak zor veya çok daha az belirgin / okunaklı olabilir.)

Bu soruyu C ++ ile ilgili blog yayından bulduğumdan , C ++ stilimin aynı olduğunu ekleyeceğim:

if (cond1 == "val1" and cond22 == "val2"
and cond333 == "val3" and cond4444 == "val4") {
    do_something
}

3

Sade ve basit, ayrıca pep8 kontrollerini de geçer:

if (
    cond1 and
    cond2
):
    print("Hello World!")

Son zamanlarda, allve anyişlevlerini tercih ediyorum, çünkü And ve Or karşılaştırmalarını nadiren karıştırıyorum ve bu iyi çalışıyor ve Jeneratörlerin Anlayışı ile Erken Başarısızlık ek avantajına sahip:

if all([
    cond1,
    cond2,
]):
    print("Hello World!")

Sadece tek bir yinelenebilir geçmek unutmayın! N argümanlarını iletmek doğru değil.

Not: anybirçok orkarşılaştırma allgibidir, birçok andkarşılaştırma gibidir.


Bu, jeneratör kavrayışlarıyla güzel bir şekilde birleşir, örneğin:

# Check if every string in a list contains a substring:
my_list = [
    'a substring is like a string', 
    'another substring'
]

if all('substring' in item for item in my_list):
   print("Hello World!")

# or

if all(
    'substring' in item
    for item in my_list
):
    print("Hello World!")

Daha fazla bilgi için: jeneratör kavrama


1
Ayrıca, pylint'in stok yapılandırmasının bir satırda satır devamında bir girintiyi istediğini belirtmeliyim; bu da bu planı kullanmamı caydırdı.
ThorSummoner

2

Durum ve vücut arasına yalnızca ek bir boş satır ekler ve gerisini kanonik şekilde yaparsak ne olur?

if (cond1 == 'val1' and cond2 == 'val2' and
    cond3 == 'val3' and cond4 == 'val4'):

    do_something

ps Ben boşluklar değil, her zaman sekmeleri kullanın; İnce ayar yapamıyorum ...


3
Bu, özellikle şartlı olanın gövdesi uzun olduğunda çok kafa karıştırıcı olacaktır.
Eli Bendersky

Eli ile hemfikirim, buradaki kapsülleme ve girinti uzun çizgiler için kafa karıştırıcı. Üstelik yeni kural olduğunu andve orifadeleri sonraki satırda başlamalı
virtualxtc

2

Genelde yaptığım şey:

if (cond1 == 'val1' and cond2 == 'val2' and
    cond3 == 'val3' and cond4 == 'val4'
   ):
    do_something

bu şekilde kapatma desteği ve kolon görsel olarak durumumuzun sonunu gösterir.


1
Neredeyse doğru; PEP 8 şimdi andveya öncesi kırılmayı önerir or.
virtualxtc

2

İf ifadesi için çok koşullu olan tüm katılımcılar da sunulan sorun kadar çirkin. Bu sorunu aynı şeyi yaparak çözemezsiniz.

PEP 0008 yanıtı bile iticidir.

İşte çok daha okunabilir bir yaklaşım

condition = random.randint(0, 100) # to demonstrate
anti_conditions = [42, 67, 12]
if condition not in anti_conditions:
    pass

Sözlerimi yememi ister misin? Beni çok koşullu koşullara ihtiyacınız olduğuna ikna edin ve ben bunu gerçekten yazdırabilir ve eğlenceniz için yiyeceğim.


Bu gerçekten çok koşullu yapmanın çok düzgün bir yoludur :) neden daha fazla oy yok bilmiyorum :), herhangi bir uyarı var mı?
dim_user

@SaulCruz gerçekten değil Sadece koşul değişkeninin tekrarlanması gerekmez, aynı zamanda her bir değeri kontrol etmek için birçok kopyadan tasarruf edersiniz, bu sadece bir dizideki değerleri koyar ve motorun (optimize edilmiş) işi yapmasına izin verir durumu sizin için kontrol
Stoff

@Stoff Yorumumu kaldırdığınız için teşekkür ederiz. Yaklaşımınızın OP'nin sorusunu yanıtlamadığını belirtmek istedim. Sağladığınız kod, sorudaki koda uygulanamaz. Aksi düşünüyorsanız, noktanızı kanıtlamak için yaklaşımınızın yeniden biçimlendirdiği OP kodunu eklemelisiniz.
Jeyekomon

Kabul edilen cevap değildir, ancak açıkça alternatif bir yaklaşımdır (diğerleri kabul eder). SO alternatif cevapları teşvik etti, bu yüzden argüman tam olarak nedir? Kendi sorunuzda açık olun, belki de uygun bir dikkat istiyorsanız, kendi sorunuzu açmayı düşünün. Ps Ben bir SO mod değilim, yorum kaldıramıyorum
Stoff

2

Bence @ zkanda'nın çözümü küçük bir bükülme ile iyi olurdu. Koşullarınız ve değerleriniz kendi listelerinde olsaydı, karşılaştırma yapmak için bir liste kavrama kullanabilirsiniz, bu da koşul / değer çiftleri eklemek için işleri biraz daha genel hale getirir.

conditions = [1, 2, 3, 4]
values = [1, 2, 3, 4]
if all([c==v for c, v in zip(conditions, values)]):
    # do something

Eğer böyle bir ifadeyi kodlamak isteseydim, okunaklılık için şöyle yazardım:

if (condition1==value1) and (condition2==value2) and \
   (condition3==value3) and (condition4==value4):

Ve sadece bir iandoperatörle başka bir çözüm atmak için :

proceed = True
for c, v in zip(conditions, values):
    proceed &= c==v

if proceed:
    # do something

1
Sadece eğlence için: all(map(eq, have, expected)). (ile from operator import eq)
Gabriel Garcia

1

Tamlık uğruna sadece birkaç rastgele fikir. Sizin için çalışıyorlarsa kullanın. Aksi takdirde, muhtemelen başka bir şey denemek daha iyidir.

Bunu bir sözlükle de yapabilirsiniz:

>>> x = {'cond1' : 'val1', 'cond2' : 'val2'}
>>> y = {'cond1' : 'val1', 'cond2' : 'val2'}
>>> x == y
True

Bu seçenek daha karmaşıktır, ancak bunu yararlı da bulabilirsiniz:

class Klass(object):
    def __init__(self, some_vars):
        #initialize conditions here
    def __nonzero__(self):
        return (self.cond1 == 'val1' and self.cond2 == 'val2' and
                self.cond3 == 'val3' and self.cond4 == 'val4')

foo = Klass()
if foo:
    print "foo is true!"
else:
    print "foo is false!"

Bu sizin için işe yarıyorsa, ama düşünmek için başka bir seçenek. İşte bir yol daha:

class Klass(object):
    def __init__(self):
        #initialize conditions here
    def __eq__(self):
        return (self.cond1 == 'val1' and self.cond2 == 'val2' and
               self.cond3 == 'val3' and self.cond4 == 'val4')

x = Klass(some_values)
y = Klass(some_other_values)
if x == y:
    print 'x == y'
else:
    print 'x!=y'

Son iki test etmedim, ama gitmek istediğin şey buysa kavramların seni idare etmesi için yeterli olmalı.

(Ve kayıt için, eğer bu sadece bir defalık bir şeyse, muhtemelen ilk başta sunduğunuz yöntemi kullanmaktan daha iyisinizdir. Karşılaştırmayı birçok yerde yapıyorsanız, bu yöntemler okunabilirliği arttırabilir bir tür hileli olmaları konusunda o kadar kötü hissetmezsiniz.)


1

Bunu da yapmak için iyi bir yol bulmak için uğraşıyorum, bu yüzden sadece bir fikir buldum (gümüş bir kurşun değil, çünkü bu çoğunlukla bir zevk meselesi).

if bool(condition1 and
        condition2 and
        ...
        conditionN):
    foo()
    bar()

Bu çözümde gördüğüm diğerlerine kıyasla birkaç değer buluyorum, yani, tüm koşulların dikey olarak hizalanmasına izin veren fazladan 4 boşluk (bool) elde edersiniz ve if ifadesinin gövdesi girintili olabilir açık (ish) bir yol. Bu ayrıca, boole operatörlerinin kısa devre değerlendirmesinin faydalarını korur, ancak elbette temelde hiçbir şey yapmayan bir işlev çağrısının ek yükünü ekler. Tartışmasını döndüren herhangi bir işlevin bool yerine burada kullanılabileceğini iddia edebilirsiniz (geçerli olarak), ama dediğim gibi, bu sadece bir fikir ve sonuçta bir zevk meselesi.

Yeterince komik, bunu yazarken ve "problem" hakkında düşünürken , bir fonksiyon çağrısının yükünü kaldıran başka bir fikir buldum . Ekstra parantez çiftlerini kullanarak karmaşık bir duruma girmek üzere olduğumuzu neden belirtmiyorsunuz? 2 ifadesi daha varsa, if ifadesinin gövdesine göre alt koşulların güzel bir 2 boşluk girintisini verin. Misal:

if (((foo and
      bar and
      frob and
      ninja_bear))):
    do_stuff()

Bunu sevdim çünkü ona baktığınızda, kafanızda hemen "zil , burada karmaşık bir şey oluyor!" . Evet, parantezlerin okunabilirliğe yardımcı olmadığını biliyorum, ancak bu koşullar nadiren yeterli görünmelidir ve ortaya çıktıklarında, onları durdurmalı ve yine de dikkatlice okumalısınız (çünkü karmaşıktırlar ).

Her neyse, burada görmediğim sadece iki teklif daha. Umarım bu birine yardımcı olur :)


1

İki satıra bölebilirsiniz

total = cond1 == 'val' and cond2 == 'val2' and cond3 == 'val3' and cond4 == val4
if total:
    do_something()

Ya da her seferinde bir koşul ekleyin. Bu şekilde, en azından dağınıklığı ayırır if.


1

Bu iş parçacığı eski biliyorum, ama bazı Python 2.7 kodu var ve PyCharm (4.5) hala bu dava hakkında şikayet ediyor:

if foo is not None:
    if (cond1 == 'val1' and cond2 == 'val2' and
        cond3 == 'val3' and cond4 == 'val4'):
            # some comment about do_something
            do_something

PEP8 uyarısı ile "bir sonraki mantıksal satırla aynı girintili görsel olarak girintili çizgi" ile bile, gerçek kod tamam mı? "Aşırı girintili mi?"

... Python'un mermiyi ısırmasını ve sadece kıvırcık parantezlerle gitmesini istediğim zamanlar var. Yanlışlıkla yanlış girintiden dolayı yıllar boyunca yanlışlıkla kaç hata getirildiğini merak ediyorum ...


0

Koşullarınızı bir liste halinde paketleyin, ardından ikram edin. sevmek:

if False not in Conditions:
    do_something

0

Uzun koşullara sahip olduğumda, genellikle kısa bir kod gövdesim olduğunu görüyorum. Bu durumda, vücudu iki kez girintiliyorum, böylece:

if (cond1 == 'val1' and cond2 == 'val2' and
    cond3 == 'val3' and cond4 == 'val4'):
        do_something

1
@ qarma, genişletmek ister misin? PEP 8 tarafından tavsiye edilen satır devam karakterlerini kullanmaktan kesinlikle daha iyidir
xorsyst

Bu aslında hattın devamı için geçerli bir durumdur. IMPO Parantezler bir demet veya işlev çağrısı anlamına gelir. OP kullanımı çok C benzeri, mümkün olduğunda python sözdizimini tercih ederim. Yine de evrensel olarak tercih edilmediğine inanıyorum.
Dima Tisnek

0
  if cond1 == 'val1' and \
     cond2 == 'val2' and \
     cond3 == 'val3' and \
     cond4 == 'val4':
      do_something

veya bu daha açıksa:

  if cond1 == 'val1'\
     and cond2 == 'val2'\
     and cond3 == 'val3'\
     and cond4 == 'val4':
      do_something

Bu durumda girintinin 4'ün katı olması için bir neden yoktur, örneğin bkz. "Açıcı ayırıcı ile hizalanmış":

http://google-styleguide.googlecode.com/svn/trunk/pyguide.html?showone=Indentation#Indentation


Google'ın kılavuzu ayrıca OP tarafından belirtildiği gibi “bunu yapmanın en belirgin yolu” ile eşleşen karmaşık bir duruma ilişkin bir örnek sunmaktadır . Her ne kadar rehber, uzun "if" ları bu şekilde biçimlendirmeyi açıkça savunmasa da.
Anton Strogonoff

0

İşte başka bir yaklaşım:

cond_list = ['cond1 == "val1"','cond2=="val2"','cond3=="val3"','cond4=="val4"']
if all([eval(i) for i in cond_list]):
 do something

Bu ayrıca, listeye başka bir koşul ekleyerek if ifadesini değiştirmeden kolayca başka bir koşul eklemeyi kolaylaştırır:

cond_list.append('cond5=="val5"')

0

Genellikle kullanıyorum:

if ((cond1 == 'val1' and cond2 == 'val2' and
     cond3 == 'val3' and cond4 == 'val4')):
    do_something()

0

if & else koşulumuz, aşağıdaki gibi yazabileceğimizden çok sayıda ifade yürütmek zorundaysa. İçimizde bir ifade ile başka örnek varsa.

Teşekkürler benim için çalışıyor.

#!/usr/bin/python
import sys
numberOfArgument =len(sys.argv)
weblogic_username =''
weblogic_password = ''
weblogic_admin_server_host =''
weblogic_admin_server_port =''


if numberOfArgument == 5:
        weblogic_username = sys.argv[1]
        weblogic_password = sys.argv[2]
        weblogic_admin_server_host =sys.argv[3]
        weblogic_admin_server_port=sys.argv[4]
elif numberOfArgument <5:
        print " weblogic UserName, weblogic Password and weblogic host details are Mandatory like, defalutUser, passwordForDefaultUser, t3s://server.domainname:7001 ."
        weblogic_username = raw_input("Enter Weblogic user Name")
        weblogic_password = raw_input('Enter Weblogic user Password')
        weblogic_admin_server_host = raw_input('Enter Weblogic admin host ')
        weblogic_admin_server_port = raw_input('Enter Weblogic admin port')
#enfelif
#endIf

0

Noobness'imi affedin, ama buradaki #Python hakkında sizin kadar bilgili olmadığım oluyor, ancak 3D BIM modellemesinde kendi nesnelerimi yazarken benzer bir şey bulduğum için algoritmamı Python'un

Burada bulduğum problem çift taraflı:

  1. Senaryoyu deşifre etmeye çalışabilecek biri için yabancı gibi görünüyor.
  2. Bu değerler değiştirilirse (en olası) veya yeni koşulların eklenmesi gerekiyorsa (bozuk şema) kod bakımı yüksek bir maliyetle gelir

Tüm bu sorunları atlamak için komut dosyanızın böyle gitmesi gerekir

param_Val01 = Value 01   #give a meaningful name for param_Val(i) preferable an integer
param_Val02 = Value 02
param_Val03 = Value 03
param_Val04 = Value 04   # and ... etc

conditions = 0           # this is a value placeholder

########
Add script that if true will make:

conditions = conditions + param_Val01   #value of placeholder is updated
########

### repeat as needed


if conditions = param_Val01 + param_Val02 + param_Val03 + param_Val04:
    do something

Bu yöntemin artıları:

  1. Komut dosyası okunabilir.

  2. Script bakımı kolay olabilir.

  3. koşullar, istenen koşulları temsil eden değerlerin toplamı ile 1 karşılaştırma işlemidir.
  4. Çok seviyeli koşullara gerek yok

Umarım hepinize yardım eder

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.