개발자/파이썬 Python

파이선 제어문 리얼파이선 7

지구빵집 2022. 1. 28. 09:06
반응형

 

 

제어란 프로그램의 처리, 실행 흐름을 바꿔주는 것을 말합니다. 일련의 코드는 보통 순차적으로 실행하지만 상황에 따라서 조건부 실행, 반복 실행, 분기 실행, 선택 실행, 중단, 되돌아가기, 건너뛰기 등 많은 변화를 주기도 합니다.

 

파이선 제어문 리얼파이선 7 

 

프로그램 실행 순서를 제어하는 방식에는 순차적 실행, 선택실행, 반복 실행, 재귀(순환) 실행, 예외처리, 함수 프로그램 호출, 동시 실행 등이 있으며, 모든 프로그래밍 언어에는 다양한 제어문이 존재하고 아래와 같은 형식을 가지고 있습니다. 당연히 코드 구문과 규칙은 다르지만 의미는 동일합니다. 

 

일반적인 제어문 키워드

 

  • if/else/elif 문 : 조건에 따라 달라지게 실행 함
  • while 문, do/while 문 : 조건에 따라 반복 실행의 무한 지속 여부를 결정하게 함
  • for 문 : 반복 횟수(또는,종결 조건)까지 반복 실행 함
  • break 문 : 반복되는 것을 중지토록 함
  • switch 문 : 조건에 따라 여러가지 분기를 실행하게 함 

앞에서 소개한 while 문 외에도, 파이썬은 다른 언어들에서 알려진 일반적인 흐름 제어문들을 사용하고, 나름의 변형을 가하고 있습니다.

 

if 문

 

아마도 가장 잘 알려진 문장 형은 if 문일 것입니다. 파이썬의 if문에서 주의해야 할 것은 바로 블럭을 나타내는 들여쓰기 부분입니다. 프로그래밍 언어에서는 이 부분을 들여쓰기(indentation)이라 합니다. 파이썬에서 if 문의 들여쓰기가 다르면 indentation Error가 발생합니다. 이러한 들여쓰기는 탭(tap) 또는 스페이스바(spacebar)를 사용하여 표현할 수 있습니다. 탭보다는 스페이스바를 사용해 빈 칸을 입력하는 것이 좋습니다. 둘 중 어떤 것을 사용해도 상관없으나 같은 코드 내에서는 탭이나 스페이스바 중 하나로 통일하여 사용하는 것이 좋습니다.

 

if / else 문의 맨 끝에는 콜론(:)을 반드시 기재해야 합니다. 다른 프로그래밍 언어에서는 대괄호를 사용하여 if / else 문을 구분하지만, 파이썬에서는 콜론을 사용하여 if / else 문을 구분하므로 코드가 더욱 간결해집니다.

 

예를 들어:

 

>>> x = int(input("Please enter an integer: "))
Please enter an integer: 42
>>> if x < 0:
...     x = 0
...     print('Negative changed to zero')
... elif x == 0:
...     print('Zero')
... elif x == 1:
...     print('Single')
... else:
...     print('More')
...
More

 

elif 문장은 없거나, 여러 개의 elif 문장이 있을 수 있고, 마지막 else 실행 문장은 선택적입니다. 키워드 〈elif〉 는 〈else if〉 의 줄임 표현인데, 과도한 들여 쓰기를 피하는 데 유용합니다. if … elif … elif … 시퀀스는 다른 언어들에서 발견되는 switch 나 case 문을 대신합니다.

 

if 구문 이미지&amp;amp;amp;amp;nbsp;http://www.tcpschool.com/java/java_control_condition

 

동일한 값을 여러 상수와 비교하거나 특정 유형 또는 속성을 확인하는 경우에도 동일함을 검사하는 명령문이 유용하다는 것을 알 수 있습니다. 

 

x in s, x not in s

 

파이썬에서만 사용할 수 있는 독특한 조건문이 있습니다. 바로 x in s과 x not in s 입니다.

 

in 키워드는 변수 s에 x 값이 포함되어 있다면 True를 반환하고, 포함되어 있지 않다면 False를 반환합니다.

 

반대로 not in 키워드는 변수 s에 x 값이 포함되어 있지 않다면 True를 반환하고, 포함되어 있다면 False를 반환합니다.

 

이때 변수 s의 자료형은 리스트, 튜플이나 문자열이 올 수 있습니다. in 이라는 단어의 뜻을 생각하면서 아래 예제를 살펴보면 쉽게 이해가 될 것입니다. 

 

>>> a in ['a','b','c']
False

>>> 'a' in ['a','b','c']
True

>>> 'a' not in ['a','b','c']
False

 

아래 예제에서 리스트에 sweet가 있다면 '삼키다'가 출력됩니다.

 

box =['sweet','chocolate','coke']

if 'sweet' in box:
    print("삼키다") #pass
else:
    print("뱉다")

 

 

for 문

 

파이썬에서 for 문은 C 나 파스칼에서 사용하던 것과 약간 다릅니다. (파스칼처럼) 항상 숫자의 산술적인 진행을 통해 이터레이션(반복 순회) 하거나, (C처럼) 사용자가 이터레이션 단계와 중지 조건을 정의할 수 있도록 하는 대신, 파이썬의 for 문은 임의의 시퀀스 (리스트나 문자열)의 항목들을 그 시퀀스에 들어있는 순서대로 이터레이션 합니다. 예를 들어 (말장난이 아니라):

 

>>> # Measure some strings:
... words = ['cat', 'window', 'defenestrate']
>>> for w in words:
...     print(w, len(w))
...
cat 3
window 6
defenestrate 12

 

컬렉션을 이터레이트 하는 동안 같은 컬렉션을 수정하는 코드는 올바르게 동작하도록 만들기 힘듭니다. 대신, 보통 컬렉션의 복사본으로 루프를 만들거나 새 컬렉션을 만드는 것이 더 간단합니다:

 

# Create a sample collection
users = {'Hans': 'active', 'Éléonore': 'inactive', '景太郎': 'active'}

# Strategy:  Iterate over a copy
for user, status in users.copy().items():
    if status == 'inactive':
        del users[user]

# Strategy:  Create a new collection
active_users = {}
for user, status in users.items():
    if status == 'active':
        active_users[user] = status

 

range() 함수

 

숫자들의 시퀀스로 이터레이트할 필요가 있으면, 내장 함수 range()가 편리합니다. 수열을 만듭니다:

 

>>> for i in range(5):
...     print(i)
...
0
1
2
3
4

 

range() 호출의 값의 마지막 값은 수열에 포함되지 않습니다; range(10) 은 10개의 값을 만드는데, 길이 10인 시퀀스의 항목들을 가리키는 올바른 인덱스들입니다. 범위가 다른 숫자로 시작하거나, 다른 증가분을 (음수조차 가능합니다; 때로 이것을 〈스텝(step)〉이라고 부릅니다.) 지정하는 것도 가능합니다:

 

>>>a = list(range(5, 10))
>>>print(a)
[5, 6, 7, 8, 9]

>>>b = list(range(0, 10, 3))
>>>print(b)
[0, 3, 6, 9]

>>>c = list(range(-10, -100, -30))
>>>print(c)
[-10, -40, -70]

 

리스트 시퀀스의 인덱스로 반복 순회하려면, 다음처럼 range()와 len() 을 결합할 수 있습니다:

 

>>> a = ['Mary', 'had', 'a', 'little', 'lamb']
>>> for i in range(len(a)):
...     print(i, a[i])
...
0 Mary
1 had
2 a
3 little
4 lamb

 

하지만, 그럴 때 대부분은, enumerate( ) 함수를 쓰는 것이 편리합니다, 문서 아래의 루프 테크닉을 보세요.

범위를 그냥 인쇄하면 이상한 일이 일어납니다:

 

>>> a = range(10)
>>>print(a)

range(0, 10)
>>>

 

많은 경우에 range()가 돌려준 객체는 리스트인 것처럼 동작하지만, 사실 리스트가 아닙니다. 이터레이트할 때 원하는 시퀀스 항목들을 순서대로 돌려주는 객체이지만, 실제로 리스트를 만들지 않아서 공간을 절약합니다.

 

이런 객체를 이터러블 이라고 부릅니다. 공급이 소진될 때까지 일련의 항목들을 얻을 수 있는 무엇인가를 기대하는 함수와 구조물들의 타깃으로 적합합니다. 우리는 for 문이 그런 구조물임을 보았습니다. 이터러블을 취하는 함수의 예는 sum()입니다:

 

>>> sum(range(4))  # 0 + 1 + 2 + 3
6
>>>

 

나중에 iterable을 반환하고 iterable을 인수로 취하는 더 많은 함수를 보게 될 것입니다. 자세한 내용은 자료구조 List 항목에서 다루겠습니다.

 

루프의 break 와 continue 문, 그리고 else 절

 

break 문은, C언어에서처럼, 가장 가까이서 둘러싸는 for 나 while 루프로부터 빠져나가게 만듭니다.

 

루프 문은 else 절을 가질 수 있습니다; 루프가 이터러블의 소진이나 (for의 경우) 조건이 거짓이 돼서 (while의 경우) 종료할 때 실행됩니다. 하지만 루프가 break 문으로 종료할 때는 실행되지 않습니다. 소수를 찾는 루프를 통해 다음에서 예시합니다:

 

>>> for n in range(2, 10):
...     for x in range(2, n):
...         if n % x == 0:
...             print(n, 'equals', x, '*', n//x)
...             break
...     else:
...         # loop fell through without finding a factor
...         print(n, 'is a prime number')
...
2 is a prime number
3 is a prime number
4 equals 2 * 2
5 is a prime number
6 equals 2 * 3
7 is a prime number
8 equals 2 * 4
9 equals 3 * 3

 

(이것은 올바른 코드입니다. 자세히 들여다보면: else 절은 if 문이 아니라 for 루프에 속합니다.)

 

루프와 함께 사용될 때, else 절은 if 문보다는 try 문의 else 절과 비슷한 면이 많습니다: try 문의 else 절은 예외가 발생하지 않을 때 실행되고, 루프의 else 절은 break가 발생하지 않을 때 실행됩니다. try 문과 예외에 관한 자세한 내용은 예외 처리하기를 보세요.

 

continue 문은, 역시 C에서 빌렸습니다, 루프의 다음 이터레이션에서 계속하도록 만듭니다:

 

>>> for num in range(2, 10):
...     if num % 2 == 0:
...         print("Found an even number", num)
...         continue
...     print("Found an odd number", num)
...
Found an even number 2
Found an odd number 3
Found an even number 4
Found an odd number 5
Found an even number 6
Found an odd number 7
Found an even number 8
Found an odd number 9

 

pass 문

 

pass 문은 아무것도 하지 않습니다. 문법적으로 문장이 필요하지만, 프로그램이 특별히 할 일이 없을 때 사용할 수 있습니다. 예를 들어:

 

>>> while True:
...     pass  # Busy-wait for keyboard interrupt (Ctrl+C)
...

 

최소한의 클래스를 만들 때 흔히 사용됩니다:

 

>>> class MyEmptyClass:
...     pass
...

 

pass가 사용될 수 있는 다른 장소는 새 코드를 작업할 때 함수나 조건부 바디의 자리를 채우는 것인데, 여러분이 더 추상적인 수준에서 생각할 수 있게 합니다. pass 는 조용히 무시됩니다:

 

>>> def initlog(*args):
...     pass   # Remember to implement this!
...

 

match Statements

 

match 문은 표현식을 취하고 그 값을 하나 이상의 케이스 블록으로 제공된 연속 패턴과 비교합니다. 이것은 표면적으로 C, Java 또는 JavaScript(및 기타 많은 언어)의 switch 문과 유사하지만 값에서 구성 요소(시퀀스 요소 또는 개체 속성)를 변수로 추출할 수도 있습니다. 파이선 매칭 문법을 자세히 공부하고 싶다면 Python Enhancement Proposals PEP 636 페이지를 참고하세요.

 

가장 간단한 형태는 주제 값을 하나 이상의 리터럴과 비교합니다.

 

def http_error(status):
    match status:
        case 400:
            return "Bad request"
        case 404:
            return "Not found"
        case 418:
            return "I'm a teapot"
        case _:
            return "Something's wrong with the internet"

 

마지막 블록에 유의하십시오. 《변수 이름》 은 와일드카드_ 역할을 하며 절대 일치하지 않습니다. 대소문자가 일치하지 않으면 분기가 실행되지 않습니다.

 

|(《or》) 를 사용하여 여러 리터럴을 단일 패턴으로 결합할 수 있습니다 .

 

case 401 | 403 | 404:
    return "Not allowed"

 

패턴은 할당을 풀고 있는 것처럼 보일 수 있으며 변수를 바인딩하는 데 사용할 수 있습니다.

 

# point is an (x, y) tuple
match point:
    case (0, 0):
        print("Origin")
    case (0, y):
        print(f"Y={y}")
    case (x, 0):
        print(f"X={x}")
    case (x, y):
        print(f"X={x}, Y={y}")
    case _:
        raise ValueError("Not a point")

 

주의 깊게 공부하십시오! 첫 번째 패턴에는 두 개의 리터럴이 있으며 위에 표시된 리터럴 패턴의 확장으로 생각할 수 있습니다. 그러나 다음 두 패턴은 리터럴과 변수를 결합하고 변수는 주제( )의 값을 바인딩 point 합니다. 네 번째 패턴은 두 개의 값을 캡처하므로 개념적으로 unpacking assignment와 유사합니다.(x, y) = point

 

클래스를 사용하여 데이터를 구조화하는 경우 클래스 이름 뒤에 생성자와 유사한 인수 목록을 사용할 수 있지만 속성을 변수로 캡처하는 기능이 있습니다.

 

class Point:
    x: int
    y: int

def where_is(point):
    match point:
        case Point(x=0, y=0):
            print("Origin")
        case Point(x=0, y=y):
            print(f"Y={y}")
        case Point(x=x, y=0):
            print(f"X={x}")
        case Point():
            print("Somewhere else")
        case _:
            print("Not a point")

 

속성에 대한 순서를 제공하는 일부 내장 클래스(예: 데이터 클래스)와 함께 위치 매개변수를 사용할 수 있습니다. __match_args__클래스에서 특수 속성을 설정하여 패턴의 속성에 대한 특정 위치를 정의할 수도 있습니다. (《x》, 《y》)로 설정하면 다음 패턴이 모두 동일합니다(모두 y속성을 var변수에 바인딩).

 

Point(1, var)
Point(1, y=var)
Point(x=1, y=var)
Point(y=var, x=1)

 

패턴을 읽는 데 권장되는 방법은 할당 왼쪽에 추가할 확장된 형식으로 패턴을 보고 어떤 변수가 무엇으로 설정되는지 이해하는 것입니다. (위와 같은) 독립 실행형 이름만 varmatch 문에 의해 할당됩니다. 점으로 구분된 이름(예: foo.bar), 속성 이름( 이상) 또는 클래스 이름( x=위와 y=같이 옆에 《(…)》으로 인식됨 Point)은 할당되지 않습니다.

 

패턴은 임의로 중첩될 수 있습니다. 예를 들어, 짧은 포인트 목록이 있는 경우 다음과 같이 일치시킬 수 있습니다.

 

match points:
    case []:
        print("No points")
    case [Point(0, 0)]:
        print("The origin")
    case [Point(x, y)]:
        print(f"Single point {x}, {y}")
    case [Point(0, y1), Point(0, y2)]:
        print(f"Two on the Y axis at {y1}, {y2}")
    case _:
        print("Something else")

 

《guard》로 알려진 절을 if 구문 패턴에 추가할 수 있습니다. 가드가 거짓이면 계속해서 다음 케이스 블록으로 진행합니다. 값을 가져오는 것은 가드가 평가되기 전이라는 사실이 중요합니다. 

 

match point:
    case Point(x, y) if x == y:
        print(f"Y=X at {x}")
    case Point(x, y):
        print(f"Not on the diagonal")

 

이 성명서의 몇 가지 다른 주요 기능:

 

unpacking 할당과 마찬가지로 튜플 및 목록 패턴은 정확히 동일한 의미를 가지며 실제로 임의의 시퀀스와 일치합니다. 중요한 예외는 반복자 또는 문자열과 일치하지 않는다는 것입니다.

 

시퀀스 패턴은 확장된 unpacking을 지원합니다. [x, y, *rest]와 (x, y, *resr)는 unpacking 할당과 동일하게 작동합니다. * 뒤에 오는 이름( _ 포함해서) (x, y, *_)도 나머지 항목을 바인딩하지 않고 두 개 이상의 항목 시퀀스를 평가합니다.

 

매핑 패턴: {"bandwidth": b, "latency": |} 문장은 사전에서 "bandwidth"와 "latency" 값을 캡처합니다. 시퀀스 패턴과 달리 추가 키는 무시됩니다. **rest와 같은 언패킹도 지원됩니다. (하지만 **_ 는 중복될 수 있으므로 허용되지 않습니다.)

 

하위 패턴은 as 키워드를 사용하여 캡처할 수 있습니다.

 

case (Point(x1, y1), Point(x2, y2) as p2): ...

 

p2(입력이 두 점의 시퀀스인 한) 입력 의 두 번째 요소를 캡처합니다.

 

대부분의 리터럴은 동일성으로 비교되지만 싱글톤 True, False와 None 은 Identity 로 비교됩니다.

 

패턴은 명명된 상수를 사용할 수 있습니다. 캡처 변수로 해석되지 않도록 점으로 구분된 이름이어야 합니다.

 

from enum import Enum
class Color(Enum):
    RED = 'red'
    GREEN = 'green'
    BLUE = 'blue'

color = Color(input("Enter your choice of 'red', 'blue' or 'green': "))

match color:
    case Color.RED:
        print("I see red!")
    case Color.GREEN:
        print("Grass is green")
    case Color.BLUE:
        print("I'm feeling the blues :(")

 

더 자세한 설명과 추가 예를 보려면 다음을 참조하십시오. 튜토리얼 형식으로 작성된 PEP 636 입니다. 

 

여기까지 파이선 제어문에 대해 알아보았습니다. 

 

 

파이선 제어문

 

 

반응형