Styling kondisi multi-baris dalam pernyataan 'jika'? [Tutup]


677

Kadang-kadang saya memecah kondisi panjang ifmenjadi beberapa baris. Cara paling jelas untuk melakukan ini adalah:

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

Tidak terlalu menarik secara visual, karena aksi menyatu dengan kondisi. Namun, ini adalah cara alami menggunakan indentasi Python yang benar dari 4 spasi.

Untuk saat ini saya menggunakan:

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

Tapi ini tidak terlalu cantik. :-)

Bisakah Anda merekomendasikan cara alternatif?


2
Jika editor Anda menggunakan paket Python pep8 untuk mendeteksi kapan harus memperingatkan tentang pelanggaran PEP8 , Anda harus menonaktifkan kesalahan E125 atau menemukan solusi pemformatan yang memenuhi pep8kriteria paket. Masalah pep8paket # 126 adalah tentang memperbaiki paket untuk secara ketat mengikuti spesifikasi PEP8. Diskusi untuk masalah ini mencakup beberapa saran gaya juga terlihat di sini.
akaihola

1
Perhatikan bahwa untuk contoh pertama, pep8 akan membuang "E129 secara indentasi baris dengan indent yang sama dengan baris logis berikutnya".
Taylor Edmiston

Pertanyaan ini sudah sangat lama dan memiliki banyak pandangan, tetapi berdasarkan pendapat. Bahasa "tidak terlalu menarik" dan "tidak terlalu cantik" menjelaskan kriteria bahwa jawaban yang seharusnya benar adalah yang paling sesuai dengan preferensi estetika penanya (yaitu pendapat). Saya bisa mengajukan pertanyaan yang sama persis dan mengklaim itu bukan duplikat karena selera estetika saya memenuhi syarat sebagai berbeda, dan akan mengarah pada jawaban "benar" yang berbeda.
Z4-tier

@ Z4-tier: ya, ini berdasarkan opini. Tapi itu ditanyakan 12 tahun lalu. SO adalah tempat yang berbeda, lebih ramah saat itu. Baru-baru ini telah mengumpulkan downvotes karena standar SO telah berubah. Tetap saja, telah dilihat> 1 juta kali, saya harap ini lebih baik daripada merugikan di dunia. Saya pasti bisa melihat orang-orang bertanya-tanya tentang pertanyaan yang sama hari ini, mencari di Google, masuk ke diskusi ini dan menemukan itu berguna untuk mengkalibrasi pemikiran mereka. Ada beberapa jawaban pilihan untuk dipilih.
Eli Bendersky

@EliBendersky sepenuhnya setuju. Ini seperti SO memiliki krisis identitas yang sedang berlangsung: sementara itu jelas tidak sesuai dengan "aturan" (jumlah jawaban yang valid merupakan bukti untuk itu), sama jelasnya bahwa itu menambah nilai. Semua hal yang sama, saya lebih suka bekerja dengan seseorang yang telah mengembangkan pandangan yang dapat diartikulasikan dan beralasan tentang gaya pengkodean, bahkan jika pandangan mereka berbeda dari saya.
Z4-tier

Jawaban:


750

Anda tidak perlu menggunakan 4 spasi pada saluran kondisional kedua Anda. Mungkin menggunakan:

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

Juga, jangan lupa spasi putih lebih fleksibel daripada yang Anda kira:

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

Keduanya cukup jelek.

Mungkin kehilangan tanda kurung ( Panduan Gaya mencegah ini)?

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

Setidaknya ini memberi Anda beberapa perbedaan.

Atau bahkan:

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

Saya rasa saya lebih suka:

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

Berikut Panduan Gaya , yang (sejak 2010) merekomendasikan menggunakan tanda kurung.


45
Perhatikan bahwa solusi trailing \ tidak direkomendasikan oleh PEP 8. Salah satu alasannya adalah jika spasi ditambahkan secara tidak sengaja setelah a \ mungkin tidak ditampilkan di editor Anda, dan kode menjadi salah secara sintaksis.
Eric O Lebigot

14
Ini salah, panduan gaya mengatakan "Garis panjang dapat dipecah menjadi beberapa baris dengan membungkus ekspresi dalam tanda kurung. Ini harus digunakan dalam preferensi untuk menggunakan garis miring terbalik untuk kelanjutan garis." Anda dapat melihat ini di sini: python.org/dev/peps/pep-0008/#maximum-line-length
joshcartme

8
@joshcartme PEP berubah di hg.python.org/peps/rev/7a48207aaab6 untuk secara eksplisit mencegah backslash. Saya akan memperbarui jawabannya.
Harley Holcombe

3
Terima kasih, mungkin juga ide yang baik untuk memperbarui contoh Anda karena sekarang tidak direkomendasikan. Saya mencoba untuk mencari tahu sendiri dan bingung oleh perbedaan antara jawaban Anda dan panduan gaya (maka komentar saya). Saya tidak hanya mencoba menjadi orang yang bertele-tele.
joshcartme

3
PEP 8 sekarang mencegah patah setelah anddan ifjuga.
virtualxtc

124

Saya telah menggunakan yang berikut ini dalam kasus degenerasi di mana itu hanya AND atau OR.

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

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

Ini mencukur beberapa karakter dan membuatnya jelas bahwa tidak ada kehalusan kondisi.


4
Ini merupakan pendekatan yang menarik. Namun tidak membahas masalah kondisi panjang
Eli Bendersky

20
Tidak apa-apa jika Anda tidak peduli tentang hubungan pendek.
Constantin

63
shortcirtuiting tidak selalu tentang cepat. Sementara tidak baik coding latihan, Anda mungkin memiliki kode seperti ini sudah ada: if destroy_world and DestroyTheWorld() == world_is_destroyed: .... Hebat, sekarang Anda baru saja menghancurkan dunia karena kecelakaan. BAGAIMANA BISA ANDA?
Aaron

4
Saya terkejut bahwa ini memiliki begitu banyak upvotes. Jawaban ini sepenuhnya mengabaikan pertanyaan awal tentang penataan kondisional multi-baris .
Przemek D

2
Ungkapan ini tidak malas. Jadi itu tidak setara jika beberapa kondisi penjagaan diikuti oleh kemungkinan gagal.
eugene-bright

57

Seseorang harus memperjuangkan penggunaan spasi putih vertikal di sini! :)

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

Ini membuat setiap kondisi terlihat jelas. Ini juga memungkinkan ekspresi yang lebih bersih dari kondisi yang lebih kompleks:

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

Ya, kami memperdagangkan sedikit real estat vertikal untuk kejelasan. Layak IMO.


19
Ini sepertinya tidak indah atau kompatibel dengan PEP8. PEP8 mengatakan bahwa tempat yang disukai untuk istirahat di sekitar operator biner (misalnya anddan juga or) adalah setelah operator, bukan sebelum itu.
Chris Medrela

7
@ChristopherMedrela apakah itu memberi tahu alasan di balik itu? Saya pikir menempatkan jeda baris sebelum operator logika jauh lebih jelas
Norill Tempest

4
Menempatkan oprerator pertama adalah sangat umum di dunia simpul. Alasannya adalah bahwa kita memperhatikan dan membaca hal-hal di sebelah kiri jauh lebih cepat daripada hal-hal di sebelah kanan - setidaknya di budaya barat. Sangat valid dalam JavaScript, di mana koma yang dilupakan dapat menyebabkan kesalahan diam.
tomekwi

11
Tolong jangan lakukan ini. Tidak hanya itu PEP8tetapi juga membuat lebih sulit untuk menentukan operasi logika yang Anda gunakan. Saya akan gagal dalam hal ini jika datang ke meja saya melalui review kode.
Urda

11
Pada versi PEP8 saat ini, melanggar baik sebelum atau sesudah operator biner dianggap dapat diterima , dan sebelum operator dianggap lebih baik untuk kode baru.
Soren Bjornstad

31

Saya lebih suka gaya ini ketika saya memiliki kondisi jika sangat besar:

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

2
+1 untuk menjaga indentasi tempat Anda dapat melacaknya. Saya suka python dan banyak menggunakannya, tapi saya terus-menerus terganggu oleh dipaksa untuk indentasi. Garis multi jika benar-benar menghancurkan estetika, bahkan ketika dilakukan dengan baik.
mayypile

4
Perhatikan bahwa memiliki operator Anda anddan orpada awal baris melanggar PEP 0008 , yang menyatakan "Tempat yang disukai untuk istirahat di sekitar operator biner adalah setelah operator, bukan sebelum itu." . Saya suka memiliki braket penutup dan titik dua pada saluran mereka sendiri untuk memisahkan kondisi if dari bodi, dan (sangat mungkin untuk melakukan ini sambil menjaga operator boolean Anda di akhir baris untuk kepatuhan PEP-0008).
Mark Amery

8
pada 2016: 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.(Gaya Knuth memulai garis dengan operator).
cowbert

27

Inilah pendapat saya yang sangat pribadi: kondisi lama (dalam pandangan saya) adalah bau kode yang menyarankan refactoring ke fungsi / metode pengembalian boolean. Sebagai contoh:

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

Sekarang, jika saya menemukan cara untuk membuat kondisi multi-line terlihat bagus, saya mungkin akan menemukan diri saya puas dengan memilikinya dan melewatkan refactoring.

Di sisi lain, membiarkan mereka mengganggu indera estetika saya bertindak sebagai insentif untuk refactoring.

Kesimpulan saya, oleh karena itu, adalah bahwa beberapa kondisi garis harus terlihat jelek dan ini merupakan insentif untuk menghindarinya.


23

Ini tidak banyak membaik tetapi ...

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

if allCondsAreOK:
   do_something

1
Alternatif yang menarik. Tapi 2 baris tambahan :-)
Eli Bendersky

Tidak akan benar-benar bekerja dengan baik dalam loop berulang, tidak akan bekerja dengan fungsi melakukan sesuatu ... dan bersikap adil - jelek
Mez

9
brian, aku sebagian tidak setuju. Menggunakan variabel untuk hasil perhitungan menengah dapat membuat kode lebih mudah dipahami, dan dalam bahasa yang dikompilasi tidak akan memiliki dampak kinerja. Itu mungkin akan dilakukan dengan python, meskipun saya tidak akan menggunakan python sama sekali jika kinerja itu penting.
Mark Baker

1
@ MarkBaker Saya dulu setuju dengan apa yang Anda tulis, sampai saya membaca Martin Fowlers "Refactoring". Dia memberikan argumen yang sangat bagus bahwa variabel perantara seperti itu menyebabkan lebih banyak kerugian daripada manfaat. Mereka menghambat refactoring berikutnya. Melakukan tanpa mereka mengarah ke gaya pemrograman yang lebih fungsional, yang cocok untuk refactoring. Ini mengejutkan saya, tetapi saya percaya dia benar, dan sejak itu berupaya menghilangkan perantara yang tidak perlu seperti ini dari kode saya - bahkan jika mereka digunakan lebih dari sekali.
Jonathan Hartley

2
Bagus, tapi mengapa camelCase ?! :)
Leonid Shvechikov

19

Saya sarankan memindahkan andkata kunci ke baris kedua dan membuat indentasi semua baris yang berisi kondisi dengan dua spasi alih-alih empat:

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

Inilah cara saya memecahkan masalah ini dalam kode saya. Memiliki kata kunci sebagai kata pertama dalam garis membuat kondisi jauh lebih mudah dibaca, dan mengurangi jumlah ruang semakin membedakan kondisi dari tindakan.


9
Saya membaca suatu tempat di Gries atau Djikstra yang menempatkan operator logika di garis depan - membuat lebih terlihat - membantu. Dan saya sudah melakukan itu sejak tahun 90-an. Dan itu membantu.
S.Lott

7
Perhatikan bahwa Panduan Gaya merekomendasikan menempatkan kondisional pada akhir baris.
Harley Holcombe

3
Itu benar, meskipun saya tidak pernah setuju dengan hal ini. Lagipula itu hanya panduan.
DzinX

8
PEP8 tidak lagi merekomendasikan menempatkan kondisi pada akhir baris.
Soren Bjornstad

14

Tampaknya layak mengutip PEP 0008 (panduan gaya resmi Python), karena berkomentar tentang masalah ini panjang lebar:

Ketika bagian kondisional dari suatu- ifpernyataan cukup panjang untuk mengharuskan itu dituliskan di beberapa baris, perlu dicatat bahwa kombinasi dari kata kunci dua karakter (yaitu if), ditambah spasi tunggal, ditambah tanda kurung pembukaan menciptakan sebuah 4- alami. ruang indent untuk baris-baris berikutnya dari conditional multiline. Ini dapat menghasilkan konflik visual dengan deretan kode indentasi yang bersarang di dalam- ifpernyataan, yang juga secara alami akan menjorok ke 4 spasi. PEP ini tidak mengambil posisi eksplisit tentang bagaimana (atau apakah) untuk lebih jauh membedakan garis kondisional dari suite bersarang di dalam ifpernyataan. Opsi yang dapat diterima dalam situasi ini termasuk, tetapi tidak terbatas pada:

# 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()

Perhatikan "tidak terbatas pada" dalam kutipan di atas; Selain pendekatan yang disarankan dalam panduan gaya, beberapa yang disarankan dalam jawaban lain untuk pertanyaan ini juga dapat diterima.


+1 untuk PEP8. Ini harus diterima, karena (praktis berbicara) panduan gaya Python resmi.
Michael - Di mana Clay Shirky

2
Juga patut ditekankan bahwa, PEP8 secara eksplisit menyatakan pendiriannya karena PEP ini tidak mengambil posisi eksplisit tentang bagaimana (atau apakah) untuk secara visual membedakan garis kondisional tersebut dari suite bersarang di dalam pernyataan if. Opsi yang dapat diterima dalam situasi ini termasuk, tetapi tidak terbatas pada: ... (terpotong) Jadi, berhentilah berdebat, pergilah dengan sesuatu yang Anda sukai!
RayLuo

7

Inilah yang saya lakukan, ingat bahwa "semua" dan "apa saja" menerima iterable, jadi saya hanya memasukkan syarat yang panjang dalam daftar dan membiarkan "semua" melakukan pekerjaan.

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

if all(condition):
   do_something

4

Saya terkejut tidak melihat solusi pilihan saya,

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

Karena andmerupakan kata kunci, itu akan disorot oleh editor saya, dan terlihat cukup berbeda dari do_something di bawahnya.


Tetapi garis kelanjutan masih tidak membedakan dirinya dari garis logis berikutnya ...
Chris Medrela

1
Perhatikan bahwa ini adalah pelanggaran PEP 0008 ( "Tempat yang disukai untuk memutari operator biner adalah setelah operator, bukan sebelum itu" ). Apakah Anda peduli, tentu saja, itu terserah Anda.
Mark Amery

1
Kebetulan, ini bukan lagi solusi pilihan saya. ;)
Marius Gedminas

4

Menambah apa yang dikatakan @krawyoti ... Kondisi lama berbau karena sulit dibaca dan sulit dimengerti. Menggunakan fungsi atau variabel membuat kode lebih jelas. Dalam Python, saya lebih suka menggunakan ruang vertikal, melampirkan tanda kurung, dan menempatkan operator logis di awal setiap baris sehingga ekspresi tidak terlihat seperti "mengambang".

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

Jika kondisi perlu dievaluasi lebih dari sekali, seperti dalam satu whilelingkaran, maka menggunakan fungsi lokal adalah yang terbaik.


1
Selain itu, Anda dapat mendeklarasikan fungsi atau lambda untuk mengembalikan false Anda yang sebenarnya sebagai ganti membuat variabel tambahan.
Techdragon

@ Techdragon jika kondisinya harus berada di tempat lain, maka memasukkannya ke dalam blok lambda akan membutuhkan nama blok lambda untuk dinamai kemudian dapat direferensikan nanti dalam kondisi if. Jika lambda akan dinamai, mengapa dan bukan fungsi biasa setelah semua? Saya pribadi suka ungkapan boolean yang berkurang ini.
Sri Kadimisetty

Saya setuju, itulah sebabnya saya biasanya menggunakan fungsi dalam banyak kasus untuk meningkatkan keterbacaan dan kemudahan pencernaan mental ketika membaca sekilas untuk memahami aliran kontrol program. Saya menyebutkan lambda untuk memastikan bahwa opsi 'lebih kecil' juga hadir jika orang-orang sangat sadar akan ruang.
Techdragon

4

Secara pribadi, saya ingin menambahkan makna pada pernyataan if panjang. Saya harus mencari melalui kode untuk menemukan contoh yang sesuai, tetapi inilah contoh pertama yang terlintas dalam pikiran: katakanlah saya kebetulan menemukan beberapa logika unik di mana saya ingin menampilkan halaman tertentu tergantung pada banyak variabel.

Bahasa Inggris: "Jika pengguna yang masuk BUKAN seorang guru administrator, tetapi hanya guru biasa, dan bukan siswa itu sendiri ..."

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

Tentu ini mungkin terlihat baik-baik saja, tetapi membaca itu jika pernyataan itu banyak pekerjaan. Bagaimana kalau kita menetapkan logika pada label yang masuk akal. "Label" sebenarnya adalah nama variabel:

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

Ini mungkin tampak konyol, tetapi Anda mungkin memiliki kondisi lain di mana Anda HANYA ingin menampilkan item lain jika, dan hanya jika, Anda menampilkan panel guru ATAU jika pengguna memiliki akses ke panel tertentu lainnya secara default:

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

Cobalah menulis kondisi di atas tanpa menggunakan variabel untuk menyimpan dan memberi label logika Anda, dan Anda tidak hanya berakhir dengan pernyataan logis yang sangat sulit dibaca, tetapi Anda juga baru saja mengulangi sendiri. Meskipun ada pengecualian yang masuk akal, ingat: Jangan Ulangi Diri Sendiri (KERING).


3

"semua" dan "apa saja" bagus untuk banyak kondisi dengan tipe huruf yang sama. TAPI mereka selalu mengevaluasi semua kondisi. Seperti yang ditunjukkan dalam contoh ini:

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
Salah! Mereka hanya melakukannya karena Anda melakukannya. Coba semua (f () untuk f di [c1, c2]).
habnabit

2
Saya pikir dia menggunakan fungsi hanya sebagai contoh, karena dia dapat dengan mudah membuatnya mencetak sesuatu. Jika kami mempertimbangkan serangkaian ekspresi acak yang disediakan dalam daftar untuk all()itu, kecuali jika Anda akan membungkusnya masing-masing dalam lambda dan menggunakan f()trik Anda , semuanya akan dievaluasi. Dengan kata lain, Aaron: Saya pikir Anders mencoba berbicara tentang kondisi secara umum, menggunakan callable sebagai contoh khusus; tetapi jawaban Anda hanya berlaku untuk fungsi.
Brandon Rhodes

3

(Saya telah sedikit mengubah pengidentifikasi sebagai nama dengan lebar tetap tidak mewakili kode nyata - setidaknya bukan kode nyata yang saya temui - dan akan percaya pada keterbacaan contoh.)

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

Ini bekerja dengan baik untuk "dan" dan "atau" (penting bahwa mereka pertama kali berada di baris kedua), tetapi lebih sedikit untuk kondisi panjang lainnya. Untungnya, yang pertama tampaknya menjadi kasus yang lebih umum sementara yang terakhir sering mudah ditulis ulang dengan variabel sementara. (Biasanya tidak sulit, tetapi bisa sulit atau jauh lebih jelas / mudah dibaca untuk menjaga hubungan arus pendek "dan" / "atau" ketika menulis ulang.)

Karena saya menemukan pertanyaan ini dari posting blog Anda tentang C ++ , saya akan menyertakan bahwa gaya C ++ saya identik:

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

3

Polos dan sederhana, juga lolos pemeriksaan pep8:

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

Baru-baru ini saya lebih suka fungsi alldan anyfungsinya, karena saya jarang mencampurkan perbandingan Dan dan Atau ini berfungsi dengan baik, dan memiliki keuntungan tambahan Gagal Dini dengan pemahaman generator:

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

Hanya ingat untuk lulus dalam satu iterable! Melewati argumen-N tidak benar.

Catatan: anyseperti banyak orperbandingan, allseperti banyak andperbandingan.


Ini menggabungkan dengan baik dengan pemahaman generator, misalnya:

# 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!")

Lebih lanjut tentang: pemahaman generator


1
Saya juga harus menunjukkan bahwa konfigurasi stock pylint menginginkan entra indent pada kelanjutan garis dalam if; yang telah menghalangi saya untuk menggunakan skema ini.
ThorSummoner

2

Bagaimana jika kita hanya memasukkan garis kosong tambahan antara kondisi dan tubuh dan melakukan sisanya dengan cara kanonik?

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

    do_something

ps Saya selalu menggunakan tab, bukan spasi; Saya tidak bisa memperbaiki ...


3
Ini akan sangat membingungkan, terutama ketika tubuh kondisional panjang, saya pikir.
Eli Bendersky

Saya setuju dengan Eli, enkapsulasi dan indentasi di sini membingungkan untuk dialog yang panjang. Selain itu, aturan baru adalah bahwa anddan orpernyataan harus dimulai pada baris berikutnya
virtualxtc

2

Apa yang biasanya saya lakukan adalah:

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

dengan cara ini kurung kurawal dan usus besar secara visual menandai akhir dari kondisi kita.


1
Hampir benar; PEP 8 sekarang merekomendasikan untuk melanggar sebelum andatau or.
virtualxtc

2

Semua responden yang juga menyediakan multi-kondisional untuk pernyataan if sama jeleknya dengan masalah yang disajikan. Anda tidak menyelesaikan masalah ini dengan melakukan hal yang sama ..

Bahkan jawaban PEP 0008 menjijikkan.

Inilah pendekatan yang jauh lebih mudah dibaca

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

Ingin aku memakan kata-kataku? Yakinkan saya bahwa Anda membutuhkan multi-kondisi dan saya akan mencetak ini dan memakannya untuk hiburan Anda.


ini memang cara yang sangat rapi untuk melakukan multi-kondisi :) tidak tahu mengapa ia tidak memiliki lebih banyak suara :), apakah ada peringatan?
dim_user

@ SaulCruz benar-benar tidak hanya variabel kondisi tidak perlu diulangi Anda juga menghemat banyak duplikat memeriksa setiap nilai, ini hanya menempatkan nilai-nilai dalam array dan membiarkan mesin melakukan itu (dioptimalkan) pekerjaan di memeriksa kondisinya untuk Anda
Stoff

@Stoff Terima kasih telah menghapus komentar saya. Saya ingin menunjukkan bahwa pendekatan Anda tidak menjawab pertanyaan OP. Kode yang Anda berikan tidak dapat diterapkan pada kode dalam pertanyaan. Jika Anda berpikir sebaliknya maka Anda harus menambahkan kode OP diformat ulang dengan pendekatan Anda untuk membuktikan maksud Anda.
Jeyekomon

Ini bukan jawaban yang diterima namun jelas merupakan pendekatan alternatif (yang lain setuju). JADI mendorong jawaban alternatif jadi apa argumennya? Jelaskan pertanyaan Anda sendiri, mungkin pertimbangkan untuk membuka pertanyaan Anda sendiri jika Anda membutuhkan perhatian yang tepat. PS Saya bukan SO mod, saya tidak bisa menghapus komentar
Stoff

2

Saya pikir solusi @kanda akan baik dengan twist kecil. Jika Anda memiliki kondisi dan nilai di daftar masing-masing, Anda dapat menggunakan pemahaman daftar untuk melakukan perbandingan, yang akan membuat hal-hal sedikit lebih umum untuk menambahkan pasangan kondisi / nilai.

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

Jika saya benar-benar ingin membuat kode pernyataan seperti ini, saya akan menulisnya seperti ini untuk keterbacaan:

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

Dan hanya untuk melempar solusi lain di luar sana dengan seorang iandoperator :

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

if proceed:
    # do something

1
Hanya untuk bersenang-senang: all(map(eq, have, expected)). (dengan from operator import eq)
Gabriel Garcia

1

Hanya beberapa ide acak lainnya demi kelengkapan. Jika mereka bekerja untuk Anda, gunakan itu. Kalau tidak, Anda mungkin lebih baik mencoba sesuatu yang lain.

Anda juga bisa melakukan ini dengan kamus:

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

Opsi ini lebih rumit, tetapi Anda mungkin juga menganggapnya berguna:

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!"

Entah apakah itu bekerja untuk Anda, tetapi itu pilihan lain untuk dipertimbangkan. Ini satu cara lagi:

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'

Dua yang terakhir saya belum diuji, tetapi konsep harus cukup untuk membuat Anda pergi jika itu yang Anda inginkan.

(Dan sebagai catatan, jika ini hanya satu kali, Anda mungkin lebih baik menggunakan metode yang Anda sajikan pada awalnya. Jika Anda melakukan perbandingan di banyak tempat, metode ini dapat meningkatkan keterbacaan yang cukup untuk membuat Anda tidak merasa begitu buruk tentang fakta bahwa mereka agak berantakan.)


1

Saya telah berjuang untuk menemukan cara yang baik untuk melakukan ini juga, jadi saya baru saja datang dengan ide (bukan peluru perak, karena ini terutama masalah selera).

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

Saya menemukan beberapa kelebihan dalam solusi ini dibandingkan dengan yang lain yang pernah saya lihat, yaitu, Anda mendapatkan persis 4 ruang lekukan tambahan (bool), yang memungkinkan semua kondisi untuk berbaris secara vertikal, dan badan pernyataan if dapat dimasukkan ke dalam cara yang jelas (ish). Ini juga menyimpan manfaat evaluasi hubung singkat operator boolean, tetapi tentu saja menambahkan overhead panggilan fungsi yang pada dasarnya tidak melakukan apa-apa. Anda dapat berdebat (secara sah) bahwa fungsi apa pun yang mengembalikan argumennya dapat digunakan di sini alih-alih bool, tetapi seperti yang saya katakan, itu hanya sebuah gagasan dan pada akhirnya masalah selera.

Cukup lucu, ketika saya menulis ini dan berpikir tentang "masalah", saya datang dengan ide lain , yang menghilangkan overhead panggilan fungsi. Mengapa tidak menunjukkan bahwa kita akan memasuki kondisi kompleks dengan menggunakan pasangan kurung tambahan? Katakan, 2 lagi, untuk memberikan 2 spasi indentasi bagus dari sub-kondisi relatif terhadap tubuh pernyataan if. Contoh:

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

Saya agak suka ini karena ketika Anda melihatnya, sebuah lonceng dengan segera berbunyi di kepala Anda mengatakan "hei, ada hal rumit yang terjadi di sini!" . Ya, saya tahu bahwa tanda kurung tidak membantu keterbacaan, tetapi kondisi ini seharusnya jarang muncul, dan ketika itu muncul, Anda harus berhenti dan membacanya dengan cermat (karena kompleks ).

Pokoknya, hanya dua proposal lagi yang belum saya lihat di sini. Semoga ini bisa membantu seseorang :)


1

Anda dapat membaginya menjadi dua baris

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

Atau bahkan menambahkan satu syarat pada satu waktu. Dengan begitu, setidaknya itu memisahkan kekacauan dari if.


1

Saya tahu utas ini sudah lama, tetapi saya memiliki beberapa kode Python 2.7 dan PyCharm (4.5) masih mengeluh tentang hal ini:

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

Bahkan dengan peringatan PEP8 "garis indentasi visual dengan indentasi yang sama dengan baris logis berikutnya", kode sebenarnya sepenuhnya OK? Itu bukan "indentasi berlebihan?"

... ada saatnya saya berharap Python akan menggigit peluru dan hanya pergi dengan kurung kurawal. Saya bertanya-tanya berapa banyak bug yang secara tidak sengaja diperkenalkan selama bertahun-tahun karena kesalahan indentasi ...


0

Kemas kondisi Anda ke dalam daftar, lalu lakukan sesuatu Suka:

if False not in Conditions:
    do_something

0

Saya menemukan bahwa ketika saya memiliki kondisi yang panjang, saya sering memiliki kode pendek. Dalam hal ini, saya hanya menggandakan indentasi tubuh, dengan demikian:

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

1
@ qarma, maukah Anda memperluas? Ini pasti lebih baik daripada menggunakan karakter garis-kelanjutan, yang direkomendasikan oleh PEP 8
xorsyst

Ini sebenarnya adalah kasus yang valid untuk kelanjutan garis. Kurung IMPO menandakan tuple atau panggilan fungsi. Penggunaan OP sangat mirip C, saya lebih suka sintaksis python bila memungkinkan. Saya mengakui bahwa \ tidak disukai secara universal.
Dima Tisnek

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

atau jika ini lebih jelas:

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

Tidak ada alasan indentasi harus berupa kelipatan 4 dalam kasus ini, mis. Lihat "Disejajarkan dengan pembatas pembuka":

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


Panduan Google juga memberikan contoh kondisi rumit , yang cocok dengan "cara paling jelas untuk melakukan ini" seperti yang disebutkan oleh OP. Meskipun panduan ini tidak secara eksplisit menganjurkan format panjang "jika" seperti itu.
Anton Strogonoff

0

Inilah pendekatan lain:

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

Ini juga memudahkan untuk menambahkan kondisi lain dengan mudah tanpa mengubah pernyataan if dengan hanya menambahkan kondisi lain ke daftar:

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

0

Saya biasanya menggunakan:

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

0

jika kondisi if & an else kita harus menjalankan beberapa pernyataan di dalamnya, maka kita dapat menulis seperti di bawah ini. Setiap saat kita memiliki contoh lain dengan satu pernyataan di dalamnya.

Terima kasih, ini berhasil untuk saya.

#!/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

Maaf noobness saya, tetapi kebetulan saya tidak memiliki pengetahuan tentang #Python seperti kalian di sini, tetapi kebetulan saya menemukan sesuatu yang mirip ketika membuat skrip objek saya sendiri dalam pemodelan BIM 3D, jadi saya akan menyesuaikan algoritma saya dengan itu dari python.

Masalah yang saya temukan di sini, adalah dua sisi:

  1. Nilai saya terasa asing bagi seseorang yang mungkin mencoba menguraikan skrip.
  2. Pemeliharaan kode akan dikenakan biaya tinggi, jika nilai-nilai itu diubah (kemungkinan besar), atau jika kondisi baru harus ditambahkan (skema rusak)

Lakukan untuk melewati semua masalah ini, skrip Anda harus seperti ini

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

Kelebihan metode ini:

  1. Skrip dapat dibaca.

  2. Script bisa dipelihara dengan mudah.

  3. kondisi adalah operasi perbandingan 1 dengan jumlah nilai yang mewakili kondisi yang diinginkan.
  4. Tidak perlu untuk kondisi bertingkat

Semoga ini bisa membantu kalian semua

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.