Development Tip

'if'문에서 여러 줄 조건을 스타일링합니까?

yourdevel 2020. 10. 2. 23:24
반응형

'if'문에서 여러 줄 조건을 스타일링합니까?


때로는 ifs의 긴 조건 을 여러 줄로 나눕니다. 이를 수행하는 가장 확실한 방법은 다음과 같습니다.

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

행동이 조건과 조화를 이루기 때문에 시각적으로 그다지 매력적이지 않습니다. 그러나 4 공백의 올바른 Python 들여 쓰기를 사용하는 것은 자연스러운 방법입니다.

지금은 다음을 사용하고 있습니다.

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

그러나 이것은별로 예쁘지 않습니다. :-)

다른 방법을 추천 해 주시겠습니까?


두 번째 조건부 줄에 4 개의 공백을 사용할 필요가 없습니다. 아마도 다음을 사용하십시오.

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

이것은 적어도 약간의 차별화를 제공합니다.

또는:

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

다음은 2010 년부터 대괄호 ​​사용을 권장 하는 스타일 가이드 입니다.


나는 단순히 AND 또는 OR 인 퇴화 된 경우에 다음을 의지했습니다.

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

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

몇 글자를 면도하고 상태에 미묘함이 없음을 분명히합니다.


누군가 는 여기서 수직 공백 사용을 옹호해야합니다! :)

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

이렇게하면 각 조건이 명확하게 표시됩니다. 또한 더 복잡한 조건을보다 깔끔하게 표현할 수 있습니다.

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

예, 우리는 명확성을 위해 약간의 수직 부동산을 거래하고 있습니다. IMO의 가치가 있습니다.


내 개인적인 견해는 다음과 같습니다. 긴 조건은 부울 반환 함수 / 메소드로 리팩토링을 제안하는 코드 냄새입니다. 예를 들면 :

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

이제 여러 줄 조건을 멋지게 보이게하는 방법을 찾았다면 아마 그 조건에 만족하고 리팩토링을 건너 뛸 것입니다.

반면에 그것들이 내 미적 감각을 교란하게하는 것은 리팩토링에 대한 인센티브로 작용합니다.

따라서 내 결론은 다중 회선 조건이보기 흉해 보일 것이며 이는이를 피하는 인센티브라는 것입니다.


많이 개선되지는 않지만 ...

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

if allCondsAreOK:
   do_something

매우 큰 if 조건이있을 때이 스타일을 선호합니다.

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

and키워드를 두 번째 줄로 이동하고 조건이 포함 된 모든 줄을 4 개 대신 두 개의 공백으로 들여 쓰는 것이 좋습니다 .

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

이것이 바로 내 코드에서이 문제를 해결하는 방법입니다. 줄의 첫 번째 단어로 키워드를 사용하면 조건을 훨씬 더 쉽게 읽을 수 있으며 공백 수를 줄이면 조건과 동작을 더욱 구별 할 수 있습니다.


PEP 0008 (Python의 공식 스타일 가이드)을 인용 할 가치가있는 것 같습니다. 이 문제에 대해 적당한 길이로 설명하기 때문입니다.

- if문의 조건부 부분이 여러 줄에 걸쳐 작성되어야 할만큼 충분히 긴 경우, 두 문자 키워드 (예 :) if, 단일 공백, 여는 괄호의 조합이 자연스러운 4-을 생성 한다는 점에 유의할 필요가 있습니다. 여러 줄 조건부의 후속 줄에 대한 공백 들여 쓰기. 이로 인해- if내에 중첩 된 들여 쓰기 된 코드 모음과 시각적 충돌이 발생할 수 있으며 , 이는 자연스럽게 4 개의 공백으로 들여 쓰기됩니다. 이 PEP는 이러한 조건 줄을-문 내부의 중첩 된 모음과 시각적으로 구별하는 방법 (또는 여부)에 대한 명시적인 입장을 취하지 않습니다 if. 이 상황에서 허용되는 옵션에는 다음이 포함되지만 이에 국한되지는 않습니다.

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

위의 인용문에서 "제한되지 않음"에 유의하십시오. 스타일 가이드에서 제안 된 접근 방식 외에이 질문에 대한 다른 답변에서 제안 된 접근 방식도 허용됩니다.


여기에 내가하는 일이 있습니다. "all"과 "any"는 iterable을 허용하므로 목록에 긴 조건을 입력하고 "all"이 작업을 수행하도록합니다.

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

if all(condition):
   do_something

내가 선호하는 솔루션을 보지 못해서 놀랐습니다.

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

and은 키워드 이므로 편집자가 강조 표시하고 그 아래에있는 do_something과 충분히 다르게 보입니다.


개인적으로 긴 if 문에 의미를 추가하는 것을 좋아합니다. 적절한 예제를 찾기 위해 코드를 검색해야하지만 여기에 가장 먼저 떠오르는 예제가 있습니다. 여러 변수에 따라 특정 페이지를 표시하려는 기발한 논리에 부딪혔다 고 가정 해 보겠습니다.

영어 : "로그인 한 사용자가 관리자 교사가 아니지만 정규 교사이며 학생 자신이 아닌 경우 ..."

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

물론 괜찮아 보일 수도 있지만 if 문을 읽는 것은 많은 작업입니다. 논리를 레이블에 할당하는 것은 어떻습니까? "라벨"은 실제로 변수 이름입니다.

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

이것은 어리석은 것처럼 보일 수 있지만 교사 패널을 표시하거나 사용자가 기본적으로 다른 특정 패널에 액세스 할 수있는 경우에만 다른 항목을 표시하려는 또 다른 조건이있을 수 있습니다.

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

논리를 저장하고 레이블을 지정하기 위해 변수를 사용하지 않고 위의 조건을 작성해보십시오. 그러면 매우 지저분하고 읽기 어려운 논리 문이 생성 될뿐만 아니라 자신을 반복하게됩니다. 합리적인 예외가 있지만 기억하십시오 : 반복하지 마십시오 (DRY).


"all"과 "any"는 동일한 유형의 경우 여러 조건에 적합합니다. 그러나 그들은 항상 모든 조건을 평가합니다. 이 예에 표시된대로 :

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

(나는 고정 너비 이름이 실제 코드를 나타내지 않고 적어도 내가 만나는 실제 코드가 아니며 예제의 가독성을 믿기 때문에 식별자를 가볍게 수정했습니다.)

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

이것은 "and"및 "or"에 대해 잘 작동하지만 (두 번째 줄에서 첫 번째가 중요 함) 다른 긴 조건에서는 훨씬 덜 작동합니다. 다행스럽게도 전자가 더 일반적인 경우 인 것처럼 보이지만 후자는 종종 임시 변수로 쉽게 다시 작성됩니다. (일반적으로 어렵지는 않지만 다시 작성할 때 "and"/ "or"의 단락을 유지하는 것은 어렵거나 명확하지 않거나 읽기 어렵습니다.)

C ++에 대한 블로그 게시물 에서이 질문을 찾았으므로 내 C ++ 스타일이 동일하다는 것을 포함하겠습니다.

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

@krawyoti가 말한 것에 덧붙여 ... 긴 조건은 읽기 어렵고 이해하기 어렵 기 때문에 냄새가납니다. 함수 나 변수를 사용하면 코드가 더 명확 해집니다. 파이썬에서는 수직 공간을 사용하고 괄호를 묶고 논리 연산자를 각 줄의 시작 부분에 배치하여 표현식이 "부동"처럼 보이지 않게하는 것을 선호합니다.

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

while루프 에서와 같이 조건을 두 번 이상 평가해야하는 경우 로컬 함수를 사용하는 것이 가장 좋습니다.


단순하고 단순하며 pep8 검사도 통과합니다.

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

최근에는 And 및 Or 비교를 거의 혼합하지 않기 때문에 allany함수를 선호했습니다. 이것은 잘 작동하고 생성기 이해와 함께 조기 실패의 추가 이점이 있습니다.

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

하나의 iterable을 전달하는 것을 잊지 마십시오! N 인수를 전달하는 것은 올바르지 않습니다.

참고 : any많은 or비교 all와 같고 많은 and비교 와 같습니다 .


이것은 다음과 같이 생성기 이해와 잘 결합됩니다.

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

추가 정보 : 생성기 이해


조건과 본문 사이에 빈 줄만 추가하고 나머지는 표준 방식으로 수행하면 어떨까요?

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

이런 식으로 닫는 중괄호와 콜론이 우리 상태의 끝을 시각적으로 표시합니다.


if 문에 대해 다중 조건을 제공하는 모든 응답자는 제시된 문제만큼 추합니다. 똑같은 일을해서이 문제를 해결할 수는 없습니다 ..

PEP 0008 답변조차도 반발합니다.

훨씬 더 읽기 쉬운 접근 방식이 있습니다.

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

내 말을 먹을까? 다중 조건이 필요하다고 설득 해 주시면 문자 그대로 이걸 인쇄해서 재미있게 먹겠습니다.


@zkanda의 솔루션이 사소한 왜곡으로 좋을 것이라고 생각합니다. 각각의 목록에 조건과 값이있는 경우 목록 이해를 사용하여 비교를 수행 할 수 있습니다. 이렇게하면 조건 / 값 쌍을 추가하는 데 좀 더 일반적입니다.

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

이와 같은 문장을 하드 코딩하고 싶다면 가독성을 위해 다음과 같이 작성합니다.

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

그리고 iand운영자 와 함께 다른 솔루션을 던지기 위해 :

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

if proceed:
    # do something

완전성을 위해 몇 가지 다른 무작위 아이디어. 그들이 당신을 위해 일한다면 그들을 사용하십시오. 그렇지 않으면 다른 것을 시도하는 것이 좋습니다.

사전을 사용하여이 작업을 수행 할 수도 있습니다.

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

이 옵션은 더 복잡하지만 유용 할 수도 있습니다.

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

그것이 당신에게 효과가 있다면 Dunno, 그러나 고려해야 할 또 다른 옵션입니다. 한 가지 더 방법이 있습니다.

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'

마지막 두 가지는 테스트하지 않았지만 그 개념이 당신이 가고 싶은 것이라면 당신이 갈 수 있도록 충분할 것입니다.

(기록을 위해, 이것이 한 번에 불과하다면 처음에 제시 한 방법을 사용하는 것이 더 나을 것입니다. 많은 장소에서 비교를 수행하는 경우 이러한 방법은 충분히 가독성을 높일 수 있습니다. 당신은 그들이 일종의 해 키라는 사실에 대해 그렇게 나쁘지 않습니다.)


I've been struggling to find a decent way to do this as well, so I just came up with an idea (not a silver bullet, since this is mainly a matter of taste).

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

I find a few merits in this solution compared to others I've seen, namely, you get exactly an extra 4 spaces of indentation (bool), allowing all conditions to line up vertically, and the body of the if statement can be indented in a clear(ish) way. This also keeps the benefits of short-circuit evaluation of boolean operators, but of course adds the overhead of a function call that basically does nothing. You could argue (validly) that any function returning its argument could be used here instead of bool, but like I said, it's just an idea and it's ultimately a matter of taste.

Funny enough, as I was writing this and thinking about the "problem", I came up with yet another idea, which removes the overhead of a function call. Why not indicate that we're about to enter a complex condition by using extra pairs of parentheses? Say, 2 more, to give a nice 2 space indent of the sub-conditions relative to the body of the if statement. Example:

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

I kind of like this because when you look at it, a bell immediatelly rings in your head saying "hey, there's a complex thing going on here!". Yes, I know that parentheses don't help readability, but these conditions should appear rarely enough, and when they do show up, you are going to have to stop and read them carefuly anyway (because they're complex).

Anyway, just two more proposals that I haven't seen here. Hope this helps someone :)


You could split it into two lines

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

Or even add on one condition at a time. That way, at least it separates the clutter from the if.


I know this thread is old, but I have some Python 2.7 code and PyCharm (4.5) still complains about this case:

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

Even with the PEP8 warning "visually indented line with same indent as next logical line", the actual code is completely OK? It's not "over-indenting?"

...there are times I wish Python would've bit the bullet and just gone with curly braces. I wonder how many bugs have been accidentally introduced over the years due to accidental mis-indentation...


Pack your conditions into a list, then do smth. like:

if False not in Conditions:
    do_something

I find that when I have long conditions, I often have a short code body. In that case, I just double-indent the body, thus:

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

or if this is clearer:

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

There is no reason indent should be a multiple of 4 in this case, e.g. see "Aligned with opening delimiter":

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


Here's another approach:

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

This also makes it easy to add another condition easily without changing the if statement by simply appending another condition to the list:

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

I usually use:

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

if our if & an else condition has to execute multiple statement inside of it than we can write like below. Every when we have if else example with one statement inside of it .

Thanks it work for me.

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

참고URL : https://stackoverflow.com/questions/181530/styling-multi-line-conditions-in-if-statements

반응형