Tạo kiểu điều kiện đa dòng trong câu lệnh 'if'? [đóng cửa]


674

Đôi khi tôi phá vỡ các điều kiện dài trong ifmột vài dòng. Cách rõ ràng nhất để làm điều này là:

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

Không phải là rất rất hấp dẫn trực quan, bởi vì hành động pha trộn với các điều kiện. Tuy nhiên, đó là cách tự nhiên bằng cách sử dụng thụt lề Python chính xác của 4 khoảng trắng.

Hiện tại tôi đang sử dụng:

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

Nhưng điều này không phải là rất đẹp. :-)

Bạn có thể đề nghị một cách khác?


2
Nếu trình soạn thảo của bạn sử dụng gói Python pep8 để phát hiện khi nào cảnh báo về vi phạm PEP8 , bạn sẽ phải vô hiệu hóa lỗi E125 hoặc tìm giải pháp định dạng thỏa mãn pep8tiêu chí của gói. Các pep8của gói vấn đề # 126 là về sửa chữa các gói để thực hiện đúng spec PEP8. Các cuộc thảo luận cho vấn đề bao gồm một số gợi ý phong cách cũng được nhìn thấy ở đây.
akaihola

1
Lưu ý rằng với ví dụ đầu tiên, pep8 sẽ đưa ra "dòng thụt lề trực quan E129 có cùng thụt lề như dòng logic tiếp theo".
Taylor Edmiston

Câu hỏi này rất cũ và có rất nhiều lượt xem, nhưng nó dựa trên ý kiến ​​một cách dứt khoát. Ngôn ngữ "không hấp dẫn lắm" và "không đẹp lắm" đưa ra các tiêu chí mà câu trả lời được cho là đúng là câu phù hợp nhất với sở thích thẩm mỹ của người hỏi (ví dụ: một ý kiến). Tôi có thể hỏi chính xác cùng một câu hỏi và khẳng định nó không phải là một bản sao bởi vì gu thẩm mỹ của tôi đủ điều kiện nó là khác nhau, và sẽ dẫn đến một câu trả lời "đúng" khác.
Z4-tier

@ Z4-tier: có, đó là ý kiến ​​dựa trên. Nhưng nó đã được hỏi 12 năm trước. SO là một nơi khác, tử tế hơn hồi đó. Gần đây, nó đã được tích lũy downvote vì các tiêu chuẩn của SO đã thay đổi. Tuy nhiên, đã được xem> 1 triệu lần, tôi hy vọng nó sẽ tốt hơn hại trên thế giới. Tôi chắc chắn có thể thấy mọi người tự hỏi về cùng một câu hỏi ngày hôm nay, Googling nó, tiếp tục cuộc thảo luận này và thấy nó hữu ích để hiệu chỉnh suy nghĩ của họ. Có một số câu trả lời được bình chọn cao để lựa chọn.
Eli Bendersky

@EliBendersky hoàn toàn đồng ý. Giống như SO có một cuộc khủng hoảng danh tính đang diễn ra: trong khi nó rõ ràng không phù hợp với "các quy tắc" (số lượng câu trả lời hợp lệ là một minh chứng cho điều đó), rõ ràng là nó tăng thêm giá trị. Tất cả mọi thứ đều bình đẳng, tôi thà làm việc với một người đã phát triển các quan điểm rõ ràng và hợp lý về phong cách mã hóa, ngay cả khi quan điểm của họ khác với tôi.
Z4-tier

Câu trả lời:


747

Bạn không cần sử dụng 4 khoảng trắng trên dòng điều kiện thứ hai. Có thể sử dụng:

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

Ngoài ra, đừng quên khoảng trắng linh hoạt hơn bạn nghĩ:

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

Cả hai đều khá xấu.

Có thể mất dấu ngoặc ( Hướng dẫn kiểu không khuyến khích điều này)?

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

Điều này ít nhất cung cấp cho bạn một số khác biệt.

Hoặc thậm chí:

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

Tôi nghĩ rằng tôi thích:

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

Dưới đây là Hướng dẫn về Phong cách , mà (từ năm 2010) khuyên bạn nên sử dụng dấu ngoặc.


45
Lưu ý rằng các giải pháp theo dõi \ không được PEP khuyến nghị 8. ​​Một lý do là nếu một khoảng trắng được thêm vào do nhầm lẫn \ nó có thể không hiển thị trong trình chỉnh sửa của bạn và mã trở nên sai về mặt cú pháp.
Eric O Lebigot

14
Điều này là sai, hướng dẫn kiểu nói "Các dòng dài có thể được chia thành nhiều dòng bằng cách gói các biểu thức trong ngoặc đơn. Chúng nên được sử dụng để ưu tiên sử dụng dấu gạch chéo ngược để tiếp tục dòng." Bạn có thể thấy điều này ở đây: python.org/dev/peps/pep-0008/#maximum-line-length
joshcartme

8
@joshcartme PEP đã thay đổi tại hg.python.org/peps/rev/7a48207aaab6 để ngăn chặn rõ ràng dấu gạch chéo ngược. Tôi sẽ cập nhật câu trả lời.
Harley Holcombe

3
Cảm ơn, có lẽ cũng là một ý tưởng tốt để cập nhật các ví dụ của bạn vì chúng hiện không được khuyến nghị. Tôi đã cố gắng để tìm ra điều này bản thân mình và đã bị nhầm lẫn bởi sự khác biệt giữa câu trả lời của bạn và hướng dẫn phong cách (do đó nhận xét của tôi). Tôi không chỉ cố gắng trở thành người phạm tội.
joshcartme

3
PEP 8 bây giờ không khuyến khích phá vỡ sau andifcũng như.
virtualxtc

124

Tôi đã sử dụng những điều sau đây trong trường hợp suy biến trong đó đơn giản là AND hoặc OR.

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

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

Nó cạo một vài ký tự và làm rõ rằng không có sự tinh tế trong điều kiện.


4
Đây là một cách tiếp cận thú vị. Không giải quyết vấn đề về điều kiện lâu dài
Eli Bendersky

20
Sẽ ổn thôi nếu bạn không quan tâm đến shortcircuiting.
Constantin

63
shortcirtuiting không phải lúc nào cũng nhanh. Mặc dù thực hành mã hóa không tốt, bạn có thể có mã như thế này : if destroy_world and DestroyTheWorld() == world_is_destroyed: .... Tuyệt vời, bây giờ bạn vừa phá hủy thế giới một cách tình cờ. BẠN CÓ THỂ LÀM THẾ NÀO?
Aaron

3
Tôi ngạc nhiên rằng điều này có rất nhiều upvote. Câu trả lời này hoàn toàn bỏ qua câu hỏi ban đầu về kiểu dáng nhiều điều kiện.
Przemek D

2
Biểu hiện này không phải là lười biếng. Vì vậy, nó không tương đương nếu một số điều kiện bảo vệ được theo sau bởi có thể không thành công.
eugene-sáng

56

Ai đó phải vô địch sử dụng khoảng trắng dọc ở đây! :)

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

Điều này làm cho mỗi điều kiện rõ ràng. Nó cũng cho phép biểu hiện sạch hơn các điều kiện phức tạp hơn:

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

Vâng, chúng tôi đang kinh doanh một chút bất động sản dọc cho rõ ràng. Rất đáng để IMO.


19
Điều này dường như không đẹp cũng không tương thích với PEP8. PEP8 nói rằng vị trí ưa thích để ngắt xung quanh toán tử nhị phân (ví dụ andnhư or) là sau toán tử, không phải trước toán tử.
Chris Medrela

7
@ChristopherMedrela nó có nói lý do đằng sau không? tôi nghĩ rằng việc đặt ngắt dòng trước toán tử logic sẽ rõ ràng hơn nhiều
Norill Tempest

4
Đặt oprerator đầu tiên là khá phổ biến trong thế giới của nút. Lý do là chúng tôi chú ý và đọc những thứ bên trái nhanh hơn rất nhiều so với những thứ ở bên phải - ít nhất là trong các nền văn hóa phương Tây. Rất hợp lệ trong JavaScript, trong đó dấu phẩy bị quên có thể gây ra lỗi im lặng.
tomekwi

11
Đừng làm điều này xin vui lòng. Không chỉ là không PEP8mà còn khiến việc xác định hoạt động logic mà bạn đang mắc phải trở nên khó khăn hơn. Tôi sẽ bỏ qua điều này nếu nó đến bàn của tôi thông qua xem xét mã.
Urda

11
Kể từ phiên bản hiện tại của PEP8, việc phá vỡ trước hoặc sau toán tử nhị phân được coi là chấp nhận được và trước khi toán tử được coi là tốt hơn cho mã mới.
Soren Bjornstad

31

Tôi thích phong cách này khi tôi có một if-condition cực kỳ lớn:

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

2
+1 để giữ thụt lề nơi bạn có thể theo dõi chúng. Tôi thích python và sử dụng nó rất nhiều, nhưng tôi liên tục khó chịu vì bị buộc phải thụt lề như vậy. Đa dòng nếu thực sự phá hủy thẩm mỹ, ngay cả khi được thực hiện tốt.
mightypile

4
Lưu ý rằng việc các nhà khai thác andornhà khai thác của bạn ở đầu dòng vi phạm PEP 0008 , trong đó nêu rõ "Vị trí ưa thích để ngắt xung quanh toán tử nhị phân là sau toán tử, không phải trước toán tử". . Mặc dù vậy, tôi thích có khung đóng và dấu hai chấm trên dòng riêng để tách điều kiện if khỏi cơ thể (và hoàn toàn có thể làm điều này trong khi giữ các toán tử boolean của bạn ở cuối dòng để tuân thủ PEP-0008).
Đánh dấu Amery

8
kể từ năm 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.(Phong cách của Knuth bắt đầu với nhà điều hành).
cowbert

27

Đây là cách làm rất riêng của tôi: điều kiện lâu dài (theo quan điểm của tôi) là mùi mã gợi ý tái cấu trúc thành hàm / phương thức trả về boolean. Ví dụ:

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

Bây giờ, nếu tôi tìm thấy một cách để làm cho các điều kiện đa dòng trở nên tốt hơn, có lẽ tôi sẽ thấy mình hài lòng với việc có chúng và bỏ qua việc tái cấu trúc.

Mặt khác, có chúng làm nhiễu cảm giác thẩm mỹ của tôi hoạt động như một động lực để tái cấu trúc.

Do đó, kết luận của tôi là các điều kiện nhiều dòng sẽ trông xấu và đây là một động lực để tránh chúng.


23

Điều này không cải thiện quá nhiều nhưng ...

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

if allCondsAreOK:
   do_something

1
Thú vị thay thế. Nhưng 2 dòng bổ sung :-)
Eli Bendersky

Sẽ không thực sự hoạt động tốt trong một vòng lặp, sẽ không hoạt động với các chức năng đang làm gì đó ... và công bằng - xấu xí
Mez

9
brian, tôi một phần không đồng ý. Sử dụng các biến cho kết quả trung gian của phép tính có thể giúp mã dễ hiểu hơn và trong ngôn ngữ được biên dịch sẽ không có bất kỳ tác động hiệu suất nào. Nó có thể sẽ làm trong trăn, mặc dù tôi hoàn toàn không sử dụng trăn nếu nước hoa là quan trọng.
Mark Baker

1
@MarkBaker Tôi đã từng đồng ý với những gì bạn viết, cho đến khi tôi đọc Martin Fowlers "Tái cấu trúc". Ông cung cấp một lập luận tuyệt vời rằng các biến trung gian như vậy gây ra nhiều tác hại hơn là lợi ích. Họ ức chế tái cấu trúc tiếp theo. Làm mà không có chúng dẫn đến một phong cách lập trình nhiều chức năng hơn, nó cho vay chính nó để tái cấu trúc. Điều này làm tôi ngạc nhiên, nhưng tôi tin rằng anh ấy đúng, và từ đó đã cố gắng loại bỏ các trung gian không cần thiết như thế này khỏi mã của tôi - ngay cả khi chúng được sử dụng nhiều lần.
Jonathan Hartley

2
Tốt, nhưng tại sao lạc đà?! :)
Leonid Shvechikov 17/03/13

19

Tôi đề nghị di chuyển andtừ khóa sang dòng thứ hai và thụt lề tất cả các dòng có điều kiện với hai khoảng trắng thay vì bốn:

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

Đây chính xác là cách tôi giải quyết vấn đề này trong mã của mình. Có một từ khóa là từ đầu tiên trong dòng làm cho điều kiện dễ đọc hơn rất nhiều và giảm số lượng khoảng trắng tiếp tục phân biệt điều kiện với hành động.


9
Tôi đã đọc ở đâu đó trong cả Gries hoặc Djikstra rằng việc đưa toán tử logic lên hàng đầu - làm cho rõ hơn - đã giúp ích. Và tôi đã làm điều đó từ những năm 90. Và nó giúp.
S.Lott

7
Lưu ý rằng Hướng dẫn kiểu khuyên nên đặt điều kiện ở cuối dòng.
Harley Holcombe

3
Đó là sự thật, mặc dù tôi không bao giờ đồng ý với nó về điều này. Rốt cuộc, nó chỉ là một hướng dẫn.
DzinX

8
PEP8 không còn khuyến nghị đặt điều kiện ở cuối dòng.
Soren Bjornstad

13

Có vẻ như đáng trích dẫn PEP 0008 (hướng dẫn phong cách chính thức của Python), vì nó nhận xét về vấn đề này ở độ dài khiêm tốn:

Khi phần có điều kiện của một phân ifđoạn đủ dài để yêu cầu nó được viết trên nhiều dòng, điều đáng chú ý là sự kết hợp của một từ khóa hai ký tự (nghĩa là ifcộng với một khoảng trắng, cộng với dấu ngoặc đơn mở tạo ra 4 - 4 không gian thụt lề cho các dòng tiếp theo của điều kiện đa dòng. Điều này có thể tạo ra một cuộc xung đột trực quan với bộ mã được thụt lề được lồng bên trong if-statement, mà cũng sẽ tự nhiên được thụt vào 4 khoảng trắng. PEP này không có vị trí rõ ràng về cách (hoặc liệu) để phân biệt trực quan hơn các dòng có điều kiện như vậy với bộ lồng nhau bên trong if-statement. Các tùy chọn có thể chấp nhận trong tình huống này bao gồm, nhưng không giới hạn ở:

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

Lưu ý "không giới hạn" trong trích dẫn ở trên; bên cạnh các cách tiếp cận được đề xuất trong hướng dẫn phong cách, một số câu hỏi được đề xuất trong các câu trả lời khác cho câu hỏi này cũng được chấp nhận.


+1 cho PEP8. Điều này nên được chấp nhận, vì nó (thực tế nói) hướng dẫn phong cách Python chính thức.
Michael - Clay Shirky ở đâu

2
Cũng đáng nhấn mạnh rằng, PEP8 nêu rõ lập trường của mình vì PEP này không có vị trí rõ ràng về cách (hoặc liệu) để phân biệt trực quan các dòng có điều kiện như vậy với bộ lồng nhau bên trong if -statement. Các tùy chọn có thể chấp nhận trong tình huống này bao gồm, nhưng không giới hạn ở: ... ( bắn tỉa ) Vì vậy, hãy ngừng tranh luận, đi với một cái gì đó bạn thích!
RayLuo

7

Đây là những gì tôi làm, hãy nhớ rằng "tất cả" và "bất kỳ" chấp nhận một lần lặp, vì vậy tôi chỉ cần đưa một điều kiện dài vào danh sách và để "tất cả" thực hiện công việc.

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

if all(condition):
   do_something

4

Tôi ngạc nhiên khi không thấy giải pháp ưa thích của tôi,

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

andlà một từ khóa, nó được đánh dấu bởi trình soạn thảo của tôi và trông đủ khác biệt so với do_s Something bên dưới nó.


Nhưng dòng tiếp tục vẫn không phân biệt với dòng logic tiếp theo ...
Chris Medrela

1
Lưu ý rằng đây là vi phạm PEP 0008 ( "Vị trí ưa thích để vượt qua toán tử nhị phân là sau toán tử, không phải trước toán tử" ). Cho dù bạn quan tâm, tất nhiên, là tùy thuộc vào bạn.
Đánh dấu Amery

1
Ngẫu nhiên, đây không còn là giải pháp ưa thích của tôi. ;)
Marius Gedminas

4

Thêm vào những gì @krawyoti nói ... Điều kiện lâu có mùi vì chúng khó đọc và khó hiểu. Sử dụng một hàm hoặc một biến làm cho mã rõ ràng hơn. Trong Python, tôi thích sử dụng không gian dọc, bao quanh dấu ngoặc đơn và đặt các toán tử logic ở đầu mỗi dòng để các biểu thức không giống như "nổi".

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

Nếu các điều kiện cần được đánh giá nhiều lần, như trong một whilevòng lặp, thì sử dụng hàm cục bộ là tốt nhất.


1
Ngoài ra, bạn có thể khai báo một hàm hoặc lambda để trả về giá trị true của bạn thay vì tạo một biến phụ.
Techdragon

@Techdragon nếu các điều kiện phải ở nơi khác, sau đó đặt chúng vào khối lambda sẽ yêu cầu khối lambda được đặt tên để nó có thể được tham chiếu sau trong điều kiện if. Nếu một lambda sẽ được đặt tên, tại sao nó và không phải là một chức năng thường xuyên? Cá nhân tôi thích biểu thức boolean giảm này.
Sri Kadimisetty

Tôi đồng ý, đó là lý do tại sao tôi thường sử dụng một chức năng trong hầu hết các trường hợp để vừa cải thiện khả năng đọc vừa dễ tiêu hóa tinh thần khi đọc lướt để hiểu luồng điều khiển chương trình. Tôi đề cập đến lambda để đảm bảo rằng tùy chọn 'nhỏ hơn' cũng có mặt trong trường hợp mọi người đặc biệt có ý thức về không gian.
Techdragon

4

Cá nhân, tôi muốn thêm ý nghĩa cho câu lệnh if dài. Tôi sẽ phải tìm kiếm thông qua mã để tìm một ví dụ thích hợp, nhưng đây là ví dụ đầu tiên xuất hiện trong đầu: giả sử tôi tình cờ gặp một số logic kỳ quặc mà tôi muốn hiển thị một trang nhất định tùy thuộc vào nhiều biến.

Tiếng Anh: "Nếu người dùng đăng nhập KHÔNG phải là giáo viên quản trị, mà chỉ là giáo viên thông thường và bản thân họ không phải là học sinh ..."

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

Chắc chắn điều này có thể trông ổn, nhưng đọc những điều đó nếu các tuyên bố là rất nhiều công việc. Làm thế nào về chúng tôi gán logic cho nhãn có ý nghĩa. "Nhãn" thực sự là tên biến:

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

Điều này có vẻ ngớ ngẩn, nhưng bạn có thể có một điều kiện khác khi bạn CHỈ muốn hiển thị một mục khác nếu và chỉ khi bạn đang hiển thị bảng giáo viên HOẶC nếu người dùng có quyền truy cập vào bảng cụ thể khác theo mặc định:

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

Hãy thử viết điều kiện trên mà không sử dụng các biến để lưu trữ và gắn nhãn logic của bạn, và không chỉ bạn kết thúc bằng một câu lệnh logic rất lộn xộn, khó đọc, mà bạn còn tự lặp lại. Mặc dù có những trường hợp ngoại lệ hợp lý, hãy nhớ: Đừng lặp lại chính mình (DRY).


3

"Tất cả" và "bất kỳ" là tốt cho nhiều điều kiện của trường hợp cùng loại. NHƯNG họ luôn đánh giá tất cả các điều kiện. Như thể hiện trong ví dụ này:

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
Sai! Họ chỉ làm vì bạn làm. Hãy thử tất cả (f () cho f trong [c1, c2]).
thói quen

2
Tôi nghĩ rằng anh ta chỉ sử dụng các chức năng làm ví dụ, bởi vì anh ta có thể dễ dàng làm cho chúng in một cái gì đó. Nếu chúng tôi đang xem xét một loạt các biểu thức tùy ý được cung cấp trong một danh sách all()sau đó, trừ khi bạn sẽ bọc chúng trong lambda và sử dụng f()mánh khóe của bạn , tất cả chúng sẽ được đánh giá. Nói cách khác, Aaron: Tôi nghĩ rằng Anders đã cố gắng nói về các điều kiện nói chung, sử dụng các phương thức gọi như một ví dụ cụ thể; nhưng rejoinder của bạn chỉ áp dụng cho các chức năng.
Brandon Rhodes

3

(Tôi đã sửa đổi nhẹ các mã định danh dưới dạng tên có chiều rộng cố định không đại diện cho mã thực - ít nhất không phải là mã thực mà tôi gặp phải - và sẽ tin vào khả năng đọc của một ví dụ.)

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

Điều này hoạt động tốt cho "và" và "hoặc" (điều quan trọng là chúng đầu tiên trên dòng thứ hai), nhưng ít hơn nhiều đối với các điều kiện dài khác. May mắn thay, cái trước dường như là trường hợp phổ biến hơn trong khi cái sau thường dễ dàng được viết lại với một biến tạm thời. (Nó thường không khó, nhưng có thể khó hoặc ít rõ ràng / dễ đọc hơn để duy trì sự ngắn mạch của "và" / "hoặc" khi viết lại.)

Vì tôi đã tìm thấy câu hỏi này từ bài đăng trên blog của bạn về C ++ , tôi sẽ bao gồm rằng kiểu C ++ của tôi giống hệt nhau:

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

3

Đơn giản và đơn giản, cũng vượt qua kiểm tra pep8:

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

Trong thời gian gần đây, tôi thích các chức năng allanychức năng hơn, vì tôi hiếm khi kết hợp và và so sánh điều này hoạt động tốt và có thêm lợi thế là Không thành công sớm với sự hiểu biết về máy phát điện:

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

Chỉ cần nhớ để vượt qua trong một lần lặp duy nhất! Truyền trong N-argument là không chính xác.

Lưu ý: anygiống như nhiều orso sánh, allcũng giống như nhiều andso sánh.


Điều này kết hợp độc đáo với sự hiểu biết về máy phát điện, ví dụ:

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

Thêm về: hiểu máy phát điện


1
Tôi cũng nên chỉ ra rằng cấu hình cổ phiếu của pylint muốn có một sự thụt dòng về tiếp tục dòng trong một; đã không cho phép tôi sử dụng chương trình này.
ThorSummoner

2

Điều gì sẽ xảy ra nếu chúng ta chỉ chèn một dòng trống bổ sung giữa điều kiện và cơ thể và làm phần còn lại theo cách chính tắc?

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

    do_something

ps Tôi luôn sử dụng các tab, không phải dấu cách; Tôi không thể tinh chỉnh ...


3
Điều này sẽ rất khó hiểu, đặc biệt là khi cơ thể của điều kiện dài, tôi nghĩ.
Eli Bendersky

Tôi đồng ý với Eli, việc đóng gói và thụt ở đây gây nhầm lẫn cho các hàng dài. Hơn nữa, quy tắc mớiandvà các orcâu lệnh sẽ bắt đầu trên dòng tiếp theo
virtualxtc

2

Những gì tôi thường làm là:

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

bằng cách này, nẹp đóng và dấu hai chấm trực quan đánh dấu sự kết thúc của tình trạng của chúng tôi.


1
Gần đúng; PEP 8 hiện khuyên nên phá vỡ trước andhoặc or.
virtualxtc

2

Tất cả những người được hỏi cũng cung cấp nhiều điều kiện cho câu lệnh if cũng xấu như vấn đề được trình bày. Bạn không giải quyết vấn đề này bằng cách làm điều tương tự ..

Ngay cả câu trả lời PEP 0008 là phản cảm.

Đây là một cách tiếp cận dễ đọc hơn

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

Muốn tôi ăn lời không? Hãy thuyết phục tôi rằng bạn cần nhiều điều kiện và tôi thực sự sẽ in nó và ăn nó để giải trí.


Đây thực sự là một cách rất gọn gàng để thực hiện đa điều kiện :) không biết tại sao nó không có nhiều phiếu hơn :), có bất kỳ cảnh báo nào không?
dim_user

@SaulCruz thực sự không chỉ không cần lặp lại biến điều kiện mà bạn còn tiết kiệm được nhiều bản sao kiểm tra từng giá trị, điều này chỉ đơn giản là đặt các giá trị trong một mảng và để công cụ thực hiện công việc (tối ưu hóa) kiểm tra điều kiện cho bạn
Stoff

@Stoff Cảm ơn bạn đã xóa bình luận của tôi. Tôi muốn chỉ ra rằng cách tiếp cận của bạn không trả lời câu hỏi của OP. Mã bạn cung cấp không thể được áp dụng cho mã trong câu hỏi. Nếu bạn nghĩ khác thì bạn nên thêm mã OP được định dạng lại theo cách tiếp cận của bạn để chứng minh quan điểm của bạn.
Jeyekomon

Nó không phải là câu trả lời được chấp nhận tuy nhiên nó rõ ràng là một cách tiếp cận khác (những người khác đồng ý). SO khuyến khích các câu trả lời thay thế để tranh luận chính xác là gì? Hãy rõ ràng trong câu hỏi của riêng bạn, có lẽ xem xét mở câu hỏi của riêng bạn nếu bạn cần sự quan tâm đúng mức. Ps Tôi không phải là một mod SO, tôi không thể xóa bình luận
Stoff

2

Tôi nghĩ rằng giải pháp của @ zkanda sẽ tốt với một bước ngoặt nhỏ. Nếu bạn có các điều kiện và giá trị của mình trong danh sách tương ứng của riêng chúng, bạn có thể sử dụng mức độ hiểu danh sách để thực hiện so sánh, điều này sẽ khiến mọi thứ chung chung hơn một chút để thêm các cặp điều kiện / giá trị.

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

Nếu tôi muốn mã hóa một câu lệnh như thế này, tôi sẽ viết nó như thế này cho dễ đọc:

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

Và chỉ cần ném một giải pháp khác ra khỏi đó với một iandnhà điều hành :

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

if proceed:
    # do something

1
Chỉ để cho vui : all(map(eq, have, expected)). (với from operator import eq)
Gabriel Garcia

1

Chỉ cần một vài ý tưởng ngẫu nhiên khác cho sự hoàn thiện. Nếu họ làm việc cho bạn, hãy sử dụng chúng. Nếu không, có lẽ bạn nên thử một cái gì đó khác.

Bạn cũng có thể làm điều này với một từ điển:

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

Tùy chọn này phức tạp hơn, nhưng bạn cũng có thể thấy nó hữu ích:

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

Nếu điều đó phù hợp với bạn, nhưng đó là một lựa chọn khác để xem xét. Đây là một cách nữa:

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'

Hai cái cuối cùng tôi chưa thử nghiệm, nhưng các khái niệm sẽ đủ để đưa bạn đi nếu đó là những gì bạn muốn đi cùng.

(Và đối với bản ghi, nếu đây chỉ là một lần, có lẽ bạn nên sử dụng phương pháp bạn đã trình bày lúc đầu. Nếu bạn thực hiện so sánh ở nhiều nơi, các phương pháp này có thể tăng cường khả năng đọc đủ để thực hiện bạn không cảm thấy quá tệ về sự thật rằng chúng là loại hack.)


1

Tôi đã phải vật lộn để tìm ra một cách tốt để làm điều này là tốt, vì vậy tôi chỉ nảy ra một ý tưởng (không phải là một viên đạn bạc, vì đây chủ yếu là vấn đề của hương vị).

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

Tôi tìm thấy một vài ưu điểm trong giải pháp này so với các giải pháp khác mà tôi đã thấy, cụ thể là, bạn nhận được chính xác thêm 4 khoảng cách thụt lề (bool), cho phép tất cả các điều kiện xếp hàng theo chiều dọc và phần thân của câu lệnh if có thể được thụt vào một cách rõ ràng (ish). Điều này cũng giữ lợi ích của việc đánh giá ngắn mạch của các toán tử boolean, nhưng tất nhiên sẽ thêm chi phí cho một cuộc gọi hàm mà về cơ bản không có gì. Bạn có thể lập luận (một cách hợp lệ) rằng bất kỳ hàm nào trả về đối số của nó có thể được sử dụng ở đây thay vì bool, nhưng như tôi đã nói, đó chỉ là một ý tưởng và cuối cùng nó là vấn đề của hương vị.

Hài hước lắm, khi tôi đang viết bài này và nghĩ về "vấn đề", tôi đã nảy ra một ý tưởng khác , loại bỏ chi phí của một cuộc gọi chức năng. Tại sao không chỉ ra rằng chúng ta sắp bước vào một điều kiện phức tạp bằng cách sử dụng thêm các cặp dấu ngoặc đơn? Nói, thêm 2, để cung cấp 2 không gian thụt lề đẹp của các điều kiện phụ so với phần thân của câu lệnh if. Thí dụ:

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

Tôi thích điều này bởi vì khi bạn nhìn vào nó, một tiếng chuông ngay lập tức vang lên trong đầu bạn nói rằng "này, có một điều phức tạp đang diễn ra ở đây!" . Vâng, tôi biết rằng dấu ngoặc đơn không giúp dễ đọc, nhưng những điều kiện này hiếm khi xuất hiện và khi chúng xuất hiện, bạn sẽ phải dừng lại và đọc chúng cẩn thận (vì chúng phức tạp ).

Dù sao, chỉ hai đề xuất nữa mà tôi chưa thấy ở đây. Hy vọng điều này sẽ giúp được ai đó :)


1

Bạn có thể chia nó thành hai dòng

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

Hoặc thậm chí thêm vào một điều kiện tại một thời điểm. Bằng cách đó, ít nhất nó phân tách sự lộn xộn từ if.


1

Tôi biết chủ đề này đã cũ, nhưng tôi có một số mã Python 2.7 và PyCharm (4.5) vẫn phàn nàn về trường hợp này:

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

Ngay cả với cảnh báo PEP8 "dòng thụt trực quan có cùng thụt lề như dòng logic tiếp theo", mã thực tế có hoàn toàn ổn không? Nó không "thụt quá?"

... có những lúc tôi ước Python sẽ cắn viên đạn và đi bằng niềng răng xoăn. Tôi tự hỏi có bao nhiêu lỗi đã vô tình được giới thiệu trong những năm qua do sự thụt nhầm ngẫu nhiên ...


0

Đóng gói các điều kiện của bạn vào một danh sách, sau đó làm smth. giống:

if False not in Conditions:
    do_something

0

Tôi thấy rằng khi tôi có điều kiện dài, tôi thường có một cơ thể mã ngắn. Trong trường hợp đó, tôi chỉ thụt đôi cơ thể, do đó:

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

1
@qarma, bạn có muốn mở rộng không? Nó chắc chắn tốt hơn so với việc sử dụng các ký tự tiếp tục dòng, được khuyến nghị chống lại PEP 8
xorsyst

Đây thực tế là một trường hợp hợp lệ để tiếp tục dòng. Dấu ngoặc IMPO biểu thị một tuple hoặc một hàm gọi. Việc sử dụng của OP rất giống C, tôi thích cú pháp python bất cứ khi nào có thể. Tôi thừa nhận rằng \ không được ưa chuộng mặc dù.
Dima Tisnek

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

hoặc nếu điều này rõ ràng hơn:

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

Không có lý do nào thụt lề phải là bội số của 4 trong trường hợp này, ví dụ: xem "Được căn chỉnh với dấu phân cách mở":

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


Hướng dẫn của Google cũng cung cấp một ví dụ về một điều kiện phức tạp , phù hợp với cách thức rõ ràng nhất để thực hiện điều này như được đề cập bởi OP. Mặc dù hướng dẫn không rõ ràng ủng hộ việc định dạng lâu dài nếu mà theo cách đó.
Anton Strogonoff

0

Đây là một cách tiếp cận khác:

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

Điều này cũng giúp bạn dễ dàng thêm một điều kiện khác một cách dễ dàng mà không thay đổi câu lệnh if bằng cách thêm vào một điều kiện khác vào danh sách:

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

0

Tôi thường sử dụng:

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

0

nếu điều kiện if & của chúng ta phải thực thi nhiều câu lệnh bên trong nó thì chúng ta có thể viết như bên dưới. Mỗi khi chúng ta có ví dụ khác với một câu lệnh bên trong nó.

Cảm ơn nó làm việc cho tôi.

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

Xin thứ lỗi, nhưng điều đó xảy ra là tôi không am hiểu về #Python như bất kỳ ai trong số các bạn ở đây, nhưng điều đó xảy ra là tôi đã tìm thấy một thứ tương tự khi tạo kịch bản cho các đối tượng của mình trong mô hình BIM 3D, vì vậy tôi sẽ điều chỉnh thuật toán của mình thành đó là con trăn.

Vấn đề mà tôi tìm thấy ở đây, là hai mặt:

  1. Giá trị của tôi có vẻ xa lạ đối với một người có thể cố gắng giải mã kịch bản.
  2. Bảo trì mã sẽ có chi phí cao, nếu những giá trị đó được thay đổi (có thể xảy ra nhất) hoặc nếu phải thêm điều kiện mới (lược đồ bị hỏng)

Làm để bỏ qua tất cả những vấn đề này, kịch bản của bạn phải đi như thế này

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

Ưu điểm của phương pháp này:

  1. Kịch bản có thể đọc được.

  2. Kịch bản có thể dễ dàng duy trì.

  3. điều kiện là một hoạt động so sánh 1 với tổng các giá trị đại diện cho các điều kiện mong muốn.
  4. Không cần điều kiện đa cấp

Hy vọng nó sẽ giúp tất cả các bạn

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.