1. while 문
i, sum = 10, 0 while i > 0: sum += i i -= 1 print("sum:", sum)
sum: 55
while 문은 : 앞에 조건이 있고, 그 조건이 만족하는 동안 뒤의 코드 블록이 실행되는 제어문이다.2. if 문
2.1 if 문과 else 문
score = int(input("성적을 입력하세요: ")) if score > 50: grade = "P" else: grade = "NP" print("grade:", grade)
성적을 입력하세요: 85 grade: P
if 문은 while 문과 비슷하게 : 앞에 조건이 붙고, 만약 그 조건이 만족하면 뒤의 코드 블록이 실행되고, 만약 만족하지 않으면 코드 블록을 실행하지 않는 제어문이다.그리고 만약
if 문 코드 블록 뒤에 else 가 따라붙으면, if 에 붙은 조건이 만족하지 않을 경우에는 else 문 뒤의 코드 블록을 실행한다.2.2 elif 문
score = int(input("성적을 입력하세요: ")) if score > 90: grade = "A" elif score > 80: grade = "B" elif score > 70: grade = "C" elif score > 60: grade = "D" else: grade = "F" print("grade:", grade)
성적을 입력하세요: 85 grade: B
그리고
if 문 뒤에 elif 문과 함께 조건이 붙으면, if 에 붙은 조건이 만족하지 않고 elif 에 붙은 조건이 만족할 경우, elif 문 뒤의 코드 블록을 실행한다.elif 문은 마치 else 와 if 를 합쳐놓은 듯한 기능을 수행한다.elif 문 뒤에도 elif 문이나 else 문이 따라올 수도 있으며, 이는 elif 뒤에 elif 같이 계속해서 이어질 수도 있다.3. for 문
3.1 리스트를 반복하는 for 문
list = ["A", "B", "C"] for element in list: print(element)
A B C
for 문은 iterable 한 오브젝트를 받아서 반복하여 실행하는 제어문이다.iterable 오브젝트는 리스트와 같이 여러가지 요소들과 그 순서를 가질 수 있는 오브젝트이다.그래서
for 문은 in 을 사이에 두고,in 뒤에는 그 iterable 오브젝트를 두고, in 앞에는 iterable 오브젝트의 각 요소들의 for 코드 블록 안에서 쓸 변수명을 둔다.3.2 일반적인 iterable을 반복하는 for 문
dict = {"apple": "noun", "fly":"verb", "beautiful":"adjective"} for key, value in dict.items(): print(f"'{key}'의 품사: {value}")
'noun'의 품사: noun 'fly'의 품사: verb 'beautiful'의 품사: adjective
for 문에 들어가는 iterable 오브젝트는 리스트 뿐만이 아니라, 일반적인 iterable 오브젝트가 모두 들어갈 수 있다.dict.items 메소드의 경우 해당 dict 의 key와 value를 tuple로 묶어서 iterable 오브젝트로 만들어주기 때문에 예제와 for 문으로 같이 반복할 수 있다.4. range 함수
4.1 range(stop) 함수
for i in range(5): print(i)
0 1 2 3 4
range 함수는 iterable 오브젝트를 반환하는 함수이다.range(stop) 형식의 매개변수를 하나 받는 경우엔, range 함수는 0부터 주어진 수 직전의 정수까지가 반복되는 오브젝트를 반환한다.4.2 range(start, stop) 함수와 range(start, stop, step) 함수
for i in range(1, 10): print("첫번째 range:", i) print() for i in range(1, 10, 5): print("두번째 range:", i)
첫번째 range: 1 첫번째 range: 2 첫번째 range: 3 첫번째 range: 4 첫번째 range: 5 첫번째 range: 6 첫번째 range: 7 첫번째 range: 8 첫번째 range: 9 두번째 range: 1 두번째 range: 6
range(start, stop) 형식의 range 문은 start 부터 시작해서 stop 까지 반복하는 오브젝트를 반환한다.range(start, stop, step) 형식의 range 문은 위의 형식과 비슷하나, 1씩 증가하는 것이 아닌, step 값 만큼 증가가 되는 오브젝트를 반환한다.5. break, continue 문
for i in range(1, 10): if i == 5: break print("첫번째 for:", i) print() for i in range(1, 10): if i == 5: continue print("두번째 for:", i)
첫번째 for: 1 첫번째 for: 2 첫번째 for: 3 첫번째 for: 4 두번째 for: 1 두번째 for: 2 두번째 for: 3 두번째 for: 4 두번째 for: 6 두번째 for: 7 두번째 for: 8 두번째 for: 9
break 문은 for 나 while 문 같은 반복문에서 사용할 수 있고, 만약 break 가 실행되는 순간 반복을 끊고 반복되는 코드 블록을 빠져나온다.continue 문은 break 문과 비슷하게 반복문에서 사용할 수 있고, 만약 continue 가 실행되는 순간 해당 반복을 스킵하고 다음 반복을 실행한다.이 두 제어문은 현재 반복을 종료한다는 공통점이 존재하지만, 실행된 이후에 원래 반복하던 코드 블록에서 빠져나오냐 빠져나오지 못하냐에서 차이점을 보인다.
6. if 이외에서의 else 문
6.1 반복문에서의 else 문
for i in range(2, 10): for x in range(2, i): if i % x == 0: print(f"{i} = {x}×{i//x}") break else: print(f"{i}는 소수입니다.")
2는 소수입니다. 3는 소수입니다. 4 = 2×2 5는 소수입니다. 6 = 2×3 7는 소수입니다. 8 = 2×4 9 = 3×3
else 문을 if 문이 아닌 for 이나 while 같은 반복문에서 사용할 경우, 반복문이 종료되면 else 문의 코드 블록을 실행한다.만약 반복문 안에서
break 문이 실행되면 반복문의 코드 블록 뿐만 아니라, else 문의 코드 블록 또한 빠져나온다.쉽게 이해 하자면,
else 가 붙은 반복문은 else 의 코드 블록까지 하나의 반복문으로 묶이기에 break 문을 만나면 반복문 바로 뒤의 코드 블록 뿐만 아니라 else 로 인해 묶인 큰 코드 블록 전체를 빠져나온다고 생각할 수 있다.6.2 try 문에서의 else 문
try: # 에러가 발생할 수 있는 코드 pass except Exception: # 에러가 발생했을 때 실행되는 코드 pass else: # 에러가 발생하지 않았을 때 실행되는 코드 pass
그리고
else 문을 try 문에 사용할 경우, try 의 코드 블록에서 예외가 발생하지 않으면 else 문의 코드 블록을 실행한다.이와 같이
else 문은 if 문 뿐만이 아니라 반복문, try 문에도 다른 용도로 사용할 수 있다.7. pass 문
if True: pass def function(): pass class MyClass: pass
# IndentationError if True: # IndentationError def function(): # IndentationError class MyClass:
pass 문은 코드 상 아무런 작업도 하지 않는다.Python에서는
if , def , class 등의 구문에서 코드 블록을 구분하는 Indentation이 필요한데, 만약 아무 내용이 없는 코드 블록을 그대로 아무것도 채워 넣지 않으면 IndentationError 가 발생한다.따라서 개발을 할 때에, 나중에 구현할, 아직 구현되지 않은 코드 블록은 그저 비워두는 것이 아니라,
pass 문을 채워 넣어두어야 한다.8. match 문
8.1 값을 매칭하는 match 문
def grade_calculator(letter_grade: str) -> float: match letter_grade[0]: case 'A': grade = 4.0 case 'B': grade = 3.0 case 'C': grade = 2.0 case 'D': grade = 1.0 case 'F': grade = 0.0 case _: raise ValueError("Invalid letter grade. Must be start with A, B, C, D, or F.") match letter_grade[1:]: case '+': grade += 0.3 case '-': grade -= 0.3 case '' | '0': pass case _: raise ValueError("Invalid modifier. Must be '+' or '-' or empty.") return grade print("A+ 학점:", grade_calculator("A+")) print("B- 학점:", grade_calculator("B-")) print("C0 학점:", grade_calculator("C0")) print("F 학점:", grade_calculator("F"))
A+ 학점: 4.3 B- 학점: 2.7 C0 학점: 2.0 F 학점: 0.0
match 문은 다른 언어들의 switch-case문과 비슷한 기능을 하며, 패턴 매칭까지 수행할 수 있다.만약
match 뒤에 붙은 변수의 값이 case 뒤에 붙은 값과 일치한다면, 해당 case 의 코드 블록을 실행한다.case 와 case 사이에 | 를 통해 연결할 경우, 둘 중 하나의 값만 일치한다면 코드 블록을 실행한다.만약 한
case 문에 매칭될 경우 다른 case 문의 코드 블록들은 무시한다.바로 다음에 설명할
case _: 의 경우, 다른 모든 case 문들과 매칭되지 않은 경우에만 실행된다.8.2 패턴을 매칭하는 match 문
def what_is(arg_x: int, arg_y: int): match (arg_x, arg_y): case (0, 0): print("원점") case (0, y): print(f"y축 위의 점: (0, {y})") case (x, 0): print(f"x축 위의 점: ({x}, 0)") case (x, y) if x == y: print(f"y = x 위의 점: ({x}, {y})") case (asdf, qwer): print(f"일반적인 점: ({asdf}, {qwer})") case _: raise ValueError("알 수 없는 점") what_is(0, 0) what_is(0, 3) what_is(4, 4) what_is(2, 1)
원점 y축 위의 점: (0, 3) y = x 위의 점: (4, 4) 일반적인 점: (2, 1)
match 문은 값들만 매칭하는 것이 아니라, 일반적인 패턴들도 매칭할 수 있다.case 문 뒤에 변수명을 포함한 패턴이 붙는다면, 그 패턴이 매칭될 경우에 코드 블록을 실행하며, 그 블록 내부에서 변수명을 사용할 수 있다. 패턴은 변수명과 관계없이 일반적으로 매칭될 수 있으며,
asdf , qwer 과 같이 임의로 설정할 수 있고 case 블록 내에서 사용할 수 있다.앞선 예제에서 사용된
case _: 의 경우, 하나의 변수에 대해 변수명 _ 을 가진 패턴에는 모든 값이 매칭될 수 있기 때문에, 이전의 case 문에 매칭되지 않을 경우에 매칭되는 것으로 볼 수 있다.이때 변수명
_ 은 특별하게도, case의 코드 블록 내부에서 매칭된 변수를 사용하지 않고, 매칭하는 패턴으로만 사용하겠다는 관습적인 역할을 가진다.또한
case 패턴 뒤에 if 를 붙이면, 패턴이 매칭하고 if 뒤의 조건이 만족하는 경우에만 case 의 코드 블록을 실행한다.8.3 클래스 패턴 매칭
class Point: def __init__(self, x, y): self.x = x self.y = y def what_is(point: Point): match point: case Point(x = 0, y = 0): print("원점") case Point(x = 2, y = y): print(f"x좌표가 2인 점: (2, {y})") case Point(x = x, y = 3): print(f"y좌표가 3인 점: ({x}, 3)") case Point() as p if p.y == 2 * p.x: print(f"y = 2x 위의 점: ({p.x}, {p.y})") case Point() as zxcv: print(f"일반적인 점: ({zxcv.x}, {zxcv.y})") case _: raise ValueError("알 수 없는 점") what_is(Point(0, 0)) what_is(Point(2, 3)) what_is(Point(3, 6)) what_is(Point(0, 4))
원점 x좌표가 2인 점: (2, 3) y = 2x 위의 점: (3, 6) 일반적인 점: (0, 4)
클래스 인스턴스가 패턴 매칭에 쓰일 경우,
x = 2 , y = y 와 같이 생성자의 변수명을 keyword argument로 입력하여 매칭할 수 있다.또한
case 패턴 뒤에 as 를 붙이면, 가져오는 클래스 인스턴스 전체를 p 와 같이 참조하여 사용할 수 있다.class Point: __match_args__ = ('x', 'y') def __init__(self, x, y): self.x = x self.y = y def what_is(point: Point): match point: case Point(0, 0): print("원점") case Point(x, 0): print(f"x축 위의 점: ({x}, 0)") case Point(0, y): print(f"y축 위의 점: (0, {y})") case Point(x, y): print(f"일반적인 점: ({x}, {y})") case _: raise ValueError("알 수 없는 점") what_is(Point(0, 0)) what_is(Point(3, 0)) what_is(Point(0, 4)) what_is(Point(2, 3))
원점 x축 위의 점: (3, 0) y축 위의 점: (0, 4) 일반적인 점: (2, 3)
또한 클래스에
__match_args__ 를 정의함으로써 패턴 매칭에 사용될 변수들을 지정할 수 있습니다.__match_args__ 를 정의해두면 keyword argument로 매칭하는 것보다 더욱 간편하게 패턴을 매칭할 수 있습니다.8.4 리스트&딕셔너리 패턴 매칭
def list_match(arg_list: list): match arg_list: case []: print("빈 리스트") case [x]: print(f"요소가 하나인 리스트: [{x}]") case [x, y]: print(f"요소가 두 개인 리스트: [{x}, {y}]") case [x, y, 0]: print(f"요소가 세 개이고 마지막 요소가 0인 리스트: [{x}, {y}, 0]") case [x, y, *rest]: print(f"요소가 세 개 이상인 리스트: [{x}, {y}, ...{rest}]") list_match([]) list_match([1]) list_match([2, 3]) list_match([4, 5, 0]) list_match([6, 7, 8, 9, 10])
빈 리스트 요소가 하나인 리스트: [1] 요소가 두 개인 리스트: [2, 3] 요소가 세 개이고 마지막 요소가 0인 리스트: [4, 5, 0] 요소가 세 개 이상인 리스트: [6, 7, ...[8, 9, 10]]
패턴으로 리스트를 매칭할 때에는, 리스트를 unpacking하는 패턴을 만들 수 있다.
예제에서
*rest 를 패턴으로 둠으로써, 세번째 이후의 요소들을 rest 로 unpacking하여 패턴을 매칭 시킬 수 있다.def dict_match(arg_dict: dict): match arg_dict: case {"a": x}: print(f"키 'a'가 있는 딕셔너리: {{'a': {x}}}") case {"b": y, "c": 0}: print(f"키 'b'와 값이 0인 'c'가 있는 딕셔너리: {{'b': {y}, 'c': {0}}}") case {"d": x, **rest}: print(f"키 'd'가 있고 임의의 요소들이 있는 딕셔너리: {{'d': {x}, ...{rest}}}") case {}: print("빈 딕셔너리") dict_match({}) dict_match({"a": 1}) dict_match({"b": 2, "c": 0}) dict_match({"d": 3, "e": 4, "f": 5})
빈 딕셔너리 키 'a'가 있는 딕셔너리: {'a': 1} 키 'b'와 값이 0인 'c'가 있는 딕셔너리: {'b': 2, 'c': 0} 키 'd'가 있고 임의의 요소들이 있는 딕셔너리: {'d': 3, ...{'e': 4, 'f': 5}}
패턴으로 딕셔너리를 매칭할 때에는, 딕셔너리의 키의 값들을 패턴으로 만들 수 있다.
또한 예제의
**rest와 같이, 임의의 요소들을 rest 로 unpacking하여 패턴을 매칭시킬 수 있다.