Python

[Python] 조건문·반복문·함수

sian han 2025. 9. 25. 18:16

학습 자료 : https://docs.python.org/ko/3.13/tutorial/controlflow.html

자료형

파이썬은 타입 명시 없이 변수를 바로 선언할 수 있다.

  • List : 여러개의 데이터를 순서대로 저장할 수 있음
  • Tuple : List와 비슷하지만 한번 생성하면 내용을 변경할 수 없다
  • Dictionary : 키와 값 쌍으로 데이터를 저장한다

문법

조건문

if age > 20:
    print("성인")

반복문

words = ['cat', 'window', 'defenestrate']
for w in words:
    print(w, len(w))
  • 파이썬의 for 문은 인덱스를 직접 다루지 않고, 요소 자체를 순회하는 방식이 기본
  • 그래서 range() 를 사용하는데, range()는 반복문을 돌릴 때 특정 범위의 숫자를 생성해주는 유용한 함수이다. (i)에 해당하는 연속적인 숫자를 자동으로 만들어준다고 생각하면 됨

range()

for i in range(5):
    print(i)
  • 가장 기본적인 형태로, 0부터 stop 바로 앞까지의 숫자를 생성함. stop 값은 포함되지 않음
    for i in range(5, 10):
      print(i)
    start 값부터 stop 바로 앞까지의 숫자를 생성함
for i in range(0, 10, 2):
    print(i)
  • start 값부터 stop 값 바로 앞까지. step 값만큼 건너뛰면서 숫자를 생성함
for i in range(1, 5):
    filename = f"file_{i}.txt"
    print(f"{filename} 파일을 처리합니다.")
  • 위와 같이 배치프로그램 개발 시 인덱스를 활용한 반복작업을 하는 용도로 사용할 수 있음
  • f-string 을 사용하면 변수를 문자열 안에 쉽게 포함시킬 수 있다

break

break문은 현재 실행 중인 가장 가까운 반복문(for 또는 while)을 즉시 종료시킴.

for n in range(2, 10):
    for x in range(2, n):
        if n % x == 0:
            print(f"{n} equals {x} * {n//x}")
            break
  • 2부터 9까지의 숫자 n 이 소수인지 아닌지 판별하는 로직
  • break 문을 만나면 안쪽 루프가 즉시 종료된다. 이후 코드는 다시 바깥쪽 루프의 다음 n 값으로 넘어간다.

continue

continue 는 반복문에서 남은 코드들을 컨너뛰고 다음 반복으로 넘어가게 하는 명령

for i in range(1, 11):
    if i % 2 !=0:
        continue
    print(i)
  • continue 는 특정 조건이 만족되었을 때, 그 조건에 해당하는 현재 반복(iteration) 만 건너뛰고, 루프는 계속해서 다음 요소로 진행할때 사용한다.

루프의 else 절

파이썬의 for 과 while 루프에는 else 절을 붙일 수 있다. 다른 언어에서는 흔히 못보기 때문에 낯설지만, 편리한 기능이다.

  • 루프가 break 문에 의해 종료되면 else 절은 실행되지 않는다.
  • 루프가 break 문 없이 정상적으로 모든 반복을 마쳤을 때만 else 절이 실행된다.
    for n in range(2, 10):
      for x in range(2, n):
          if n % x ==0:
              print(n, 'equals', x, '*', n//x)
              break
      else:
          # 이 else 절은 안쪽 for 루프에 속함
          print(n, 'is a prime number')
  • 안쪽 루프가 끝까지 돌았는데도 약수를 하나도 찾지 못했다면 그것은 n이 소수라는 의미이기때문에 break가 실행되지 않았으므로 else 절이 실행되어 "n is a prime number"를 출력한다.
  • 이처럼 for...else 문은 모든 요소를 다 확인해 봤는데 원하는 것을 찾지 못했어 와 같은 상황을 간결하게 표현할 수 있다.

pass

pass 문은 아무런 동작도 하지 않는 빈문장이다.

파이썬에서는 코드블록에 최소한 한 줄 이상의 코드가 있어야 하는데, 때로 아직 구현할 내용이 없거나, 나중에 추가할 코드를 위해 자리를 비워두고 싶을 때 pass 를 사용한다. 이러면 에러 없이 코드를 실행할 수 있다.

def my_funtion():
    pass # TODO: 나중에 이 함수에 코드 추가하기

match

파이썬 3.10 버전부터 도입된 match 문은 자바의 switch 와 비교하면 이해가 쉽다.

파이썬의 match 문은 단순한 값 비교를 넘어서 패턴매칭이라는 강력한 기능을 제공한다.

def get_day(number):
    match number:
        case 1:
            return "월요일"
        case 2:
            return "화요일"
        case _: # 와일드 카드. 자바의 default 와 동일함
            return "알 수 없음"

match 문은 단순히 값을 비교하는 것을 넘어, 복합적인 자료형에서 내부 값을 변수로 추출할 수 있다.

point = (3, 0)
match point:
    case (0,0):
        print("Origin")
    case (0, y):
        print(f"Y={x}")
    case (x, 0):
        print(f"X={x}")
    case (x, y):
        print(f"X={x}, Y={y}")
  • 위 예제의 경우 세번째 case와 매칭되면서 print(f"X={3}") 이 실행된다.

함수

def 키워드

파이썬에서 함수를 정의할때 def 키워드를 사용한다. 함수의 본문은 반드시 들여쓰기로 구분해야 한다

def fin:
    pass

Docstring

함수 본문의 첫 번째 줄에 큰따옴표 3개("""...""")로 감싸인 문장이 있다면, 이것은 독스트링이라고 불리는 함수 설명 문서이다. 좋은 코드 습관을 위해 반드시 사용하는 것이 좋다.

def fin(n):
    """n보다 작은 피보나치 수열을 출력합니다."""
    pass

변수 스코프: 지역 vs 전역

지역 변수(local variable): 함수 안에서 정의된 변수는 함수 호출이 끝나면 사라진다. 함수 바깥에 있는 전역변수를 함수 안에서 읽는 것은 가능하지만, 직접 값을 변경하려면 global 키워드를 사용해야한다.

  • 자바에서 전역변수는 this 키워드로 접근하는데, 파이썬에서는 이 개념을 local 과 global로 구분한다.

인자 전달 : Call by Value

파이썬은 함수에 인자를 전달할 때 call by value 방식을 사용한다. 근데 여기서 중요한 점은 전달되는 값은 객체에 의한 참조 라는 것이다.

  • call by value(값에 의한 호출) : 함수 호출 시 원시 타입 인수를 함수에 매개변수로 전달할 때 매개변수에 값을 복사하여 함수로 전달하는 방식. 이때 함수 내에서 매개변수를 통해 값이 변경되어도 전달이 완료된 원시 타입 값은 변경되지 않는다.
    def modify_list(my_list):
      my_list.append(4) # 원본 리스트가 변경됨
    

my_numbers = [1, 2, 3]
modify_list(my_numbers)
print(my_numbers) # [1, 2, 3, 4]

- List와 같은 가변 객체를 함수에 인자로 넘기면, 그 함수 안에서 그 객체를 수정할 수 있다.
- [참고](https://feelfreetothink.tistory.com/221)


## 함수 객체와 변수
파이썬에서는 함수도 하나의 객체이다. 따라서 변수에 할당하거나, 다른 함수의 인자로 전달할 수 있다. 
```py
f - fib  # fib 함수 객체를 변수 f에 할당
f(100)   # f를 호출하면 fib 함수가 실행됨

이는 함수를 1급 객체로 다루는 파이썬의 중요한 특징이다.

return 과 none

  • return : 함수는 return 을 사용해 값을 반환할 수 있다
  • return 생략 : 만약 함수에 return 이 없거나 return 다음에 값이 없다면, 함수는 자동으로 none을 반환한다. none은 자바의 null과 유사함

메서드 호출과 효율성

result.append(a)result = result + [a]보다 훨씬 효율적이다. append()는 기존 리스트에 요소를 추가하는 반면, + 연산은 새로운 리스트를 만들어 메모리 낭비가 발생하기 때문이다. 이런 메서드 개념은 자바의 객체 지향 프로그래밍과 동일하게 파이썬의 클래스에서도 핵심적인 부분이다.

함수 정의 더보기

파이썬 함수의 인자에 대한 추가적인 내용설명. 자바의 오버로딩(Overloading)이나 생성자의 this()호출과 비슷한 편리함을 제공한다고 생각하면 됨.

기본 인자 값

파이썬에서는 함수를 정의할 때 인자에 기본값을 미리 지정해줄 수 있다. 이렇게 하면 함수를 호출할 때 해당 인자를 생략할 수 있다.

기본값 사용의 장점:

  • 필수 인자만 전달하여 함수를 호출할 수 있다.
  • 가장 쓸모있는 형식은 하나나 그 이상 인자들의 기본값을 지정하는 것이다. 정의된 것보다 더 적은 개수의 인자들로 호출될 수 있는 함수를 만든다.
    def ask_ok(prompt, retries=4, reminder='Please try  again!'):
      while True:
          reply = input(prompt)
          if reply in {'y', 'ye', 'yes'}:
              return True
          if reply in {'n', 'no', 'nop', 'nope'}:
              return False
          retries = retried -1 
          if retires < 0:
              raise ValueError('invalid user response')
          print(reminder)
    기본값의 중요한 주의사항 : 가변객체(Mutable Objects)기본값은 함수가 정의될 때 딱 한 번만 평가된다. 기본값으로 가변객체(List,Dictionary)를 사용하면 문제가 발생할 수 있다
    def f(a, L=[]):  # L은 기본값으로 빈 리스트를 갖는다
      L.append(a)
      return L
    

print(f(1)) # [1]
print(f(2)) # [1, 2]
print(f(3)) # [1, 2, 3]

L은 함수 호출마다 새롭게 생성되는 것이 아니라, f 함수가 메모리에 로드될 때 한 번 생성된 후 계속 공유되기 때문에 이전 호출에서 변경된 동일한 리스트를 계속 참조한다.

- 해결책 : NONE 사용하기
  - 가변 객체를 기본값으로 사용하고 싶을 때는 None 을 기본값으로 설정하는 것이 일반적인 해결책이다. 
```py
def f(a, L=None):
    if L is None:  # L이 None인지 확인(첫 호출)
        L = []     # 새로운 빈 리스트를 생성함
    L.append(a)
    return L

이렇게 하면 함수 호출간에 리스트가 공유되지 않고 매번 독립적인 리스트를 사용할 수 있다.

키워드 인자

키워드 인자는 이름=값형태로 함수에 값을 전달하는 방식이다. 일반적인 위치 인자처럼 순서에 맞춰 값을 전달할 필요 없이, 인자의 이름을 명시하여 값을 전달한다.

자바에는 없는 독특하고 강력한 기능. 자바의 메서드 오버로딩을 대체한다.

주요 특징 및 규칙

    1. 위치무관 : 키워드 인자의 순서는 중요하지 않다
      parrot(voltage=1000000, action='VOOOOOM')
      parrot(action='VOOOOOM', volatage=1000000)
    1. 키워드 인자의 위치는 항상 위치 인자 후에 : 함수 호출 시 위치 인자는 항상 키워드 인자보다 먼저 나와야 한다.
      • 키워드 인자 : 인자의 이름을 명시하기 때문에 순서가 중요하지는 않다.
      • 위치 인자 : 함수를 호출할 때 매개변수의 순서에 맞춰 값을 전달하는 일반적인 방식. 순서가 중요하다
        # parrot(위치인자, 키워드인자)
        parrot('a thousand', state='pushing up the daisies')
        **kwargs: 가변 키워드 인자함수 정의 시 마지막 매개변수에 **를 붙이면, 이는 키워드 인자를 dictionary 형태로 받을 수 있는 매개변수가 된다. 이는 자바의 @RequestParam 어노테이션과 유사한 역할을 한다.
        def cheeseshop(kind, *arguments, **keywords):
        # ...
  • kind: 필수 위치 인자
  • *arguments: 가변 위치 인자
  • **keywords: 가변 키워드 인자. 모든 키워드 인자를 딕셔너리로 묶어 keywords에 할당한다.
def cheeseshop(kind, *arguments, **keywords):
    print("-- Do you have any", kind, "?")
    print("-- I'm sorry, we're all out of", kind)
    for arg in arguments:
        print(arg)
    print("-" * 40)
    for kw in keywords:
        print(kw, ":", keywords[kw])
cheeseshop("Limburger", "It's very runny, sir.",
           "It's really very, VERY runny, sir.",
           shopkeeper="Michael Palin",
           client="John Cleese",
           sketch="Cheese Shop Sketch")
-- Do you have any Limburger ?
-- I'm sorry, we're all out of Limburger
It's very runny, sir.
It's really very, VERY runny, sir.
----------------------------------------
shopkeeper : Michael Palin
client : John Cleese
sketch : Cheese Shop Sketc

결과적으로 keywords는 다음과 같은 딕셔너리가 된다.

{
    'shopkeeper': 'Michael Palin', 
    'client': 'John Cleese', 
    'sketch': 'Cheese Shop Sketch'
}

*args: 가변 위치 인자

함수 매개변수 앞에 *를 붙이면, 해당 매개변수는 가변 위치 인자가 된다. 이 매개변수는 함수 호출 시 전달된 남은 위치 인자들을 모두 모아 하나의 튜플로 만든다.

def write_multiple_items(file, separator, *args):
    # 예: write_multiple_items(my_file, ',', 'apple', 'banana', 'cherry')
    # 이 경우 args는 ('apple', 'banana', 'cherry')가 됩니다.
    file.write(separator.join(args))
  • write_multiple_items 함수는 첫번째와 두 번째 인자를 받은 후, 나머지 모든 위치 인자를 튜플 args에 담는다.

*args는 주로 매개변수 목록의 마지막에 위치하여 남은 인자들을 모두 가져간다. 하지만 *args뒤에 매개변수가 오면, 그 매개변수는 키워드 전용 인자가 된다.

def concat(*args, sep="/"):
    # *args는 가변 위치 인자, sep은 키워드 전용 인자
    return sep.join(args)

# 1. 위치 인자로만 호출
concat("earth", "mars", "venus")
# 출력: 'earth/mars/venus'

# 2. sep을 키워드 인자로 전달
concat("earth", "mars", "venus", sep=".")
# 출력: 'earth.mars.venus.'
  • concat 함수에서 sep 매개변수는 *args 뒤에 위치하기 때문에 반드시 sep="." 처럼 키워드를 명시해서 전달해야한다. concat("earth", "mars", "venus", ".")처럼 .을 위치 인자로 전달하면 오류가 발생한다. 이는 *args가 .을 포함한 모든 위치 인자를 가져가기 때문이다.

*args는 배치 프로그램에서 정해지지 않은 수의 입력값을 처리해야 할 때 매우 유용하다. 예를 들어, 파일 경로를 인자로 받아서 한꺼번에 처리하는 함수를 만들 때 유용하게 활용할 수 있다.

인자 목록 언패킹

언패킹은 * 또는 ** 연산자를 사용하여 시퀀스(리스트,튜플)이나 매핑(딕셔너리) 객체에 담긴 요소들을 풀어서 함수의 개별 인자로 전달하는 기능

자바에서 배열이나 맵의 요소를 하나씩 꺼내서 함수의 인자로 자동으로 전달해주는 기능이라고 생각하면 됨

* 연산자 : 위치 인자 언패킹

리스트나 튜플과 같은 시퀀스 자료형 앞에 *를 붙이면, 해당 시퀀스가 각 요소의 함수의 위치 인자로 전달된다.

args = [3,6]
list(range(*args))
# list(range(3,6))
# [3, 4, 5]
  • range() 함수는 두 개의 개별 인자(start, stop)을 필요로 한다.
  • list(range(*args))는 파이썬 인터프리터에 의해 list(range(3,6))처럼 변환된다.

** 연산자: 키워드 인자 언패킹

딕셔너리와 같은 매핑 자료형 앞에 **를 붙이면, 해당 딕셔너리의 키-값 쌍이 함수의 키워드 인자로 전달된다. 이때 딕셔너리의 키는 함수의 매개변수 이름과 일치해야한다.

d = {"voltage": "four million", "state": "bleedin' demised", "action": "VOOM"}
parrot(**d)
# parrot(voltage="four million", state="bleedin' demised", action="VOOM")
  • 언패킹은 def f(*args, **kwargs)처럼 함수 정의 시 사용되는 가변 인자와는 반대 개념으로, 함수 호출 시 사용된다는 점을 기억하자

가변인자 규칙:

    1. 위치 인자는 *로 표시하고, 키워드 인자는 **로 표시한다.
    1. 함수 정의 시 순서는 (필수인자, *agrs, **kwargs)이다.

**kwargs는 배치 프로그램에서 설정 파일을 파싱하거나, 다양한 옵션을 유연하게 받는 API를 만들때 유용할 수 있다. 필수 인자 외에 여러 부가적인 옵션을 받을 때 **kwargs를 사용하면 코들르 간결하게 유지할 수 있다.

특수 매개변수 /, *

일반적으로 파이썬 함수는 인자를 위치로 전달하거나 키워드로 전달할 수 있다(위치 인자, 키워드 인자) 하지만 특정 인자를 특정 방식으로만 전달할 필요가 있을 때 이 특수 매개변수를 사용한다. 이는 코드 안정성을 높이는데 도움이 된다.

위치전용 매개변수: /

def f(pos1, pos2, /):와 같이 /앞에 있는 매개변수들은 오직 위치로만 값을 전달받을 수 있다.

키워드 전용 매개변수: *

def f(pos_or_kwd, *, kwd1, kwd2):와 같이 *뒤에 있는 매개변수들은 반드시 키워드를 명시하여 값을 전달해야 한다.

람다 표현식

람다 표현식은 lambda 키워드를 사용해 만드는 이름없는(익명) 한 줄짜리 함수이다. 일반 함수처럼 def로 정의하는 대신, 함수를 한 줄의 표현식으로 간결하게 작성할 수 있다.

자바에서 람다나 익명함수와 정확히 같은 개념임.

람다 표현식: 작고 익명인 함수

구문 : lambda 인자: 반환될_값

  • 인자: a,b 와 같이 쉼표로 구분된 인자 목록
  • 표현식: 콜론(:) 뒤에 오는 부분. 이 표현식의 결과가 자동으로 반환됨. return 키워드는 사용하지 않음
    def make_incrementor(n):
      return lambda x: x + n
    

f = make_incrementor(42)
print(f(0))
print(f(1))

make_incrementor 함수는 x 에 n 을 더하는 람다 함수를 반환한다. 이 람다 함수는 자신이 정의된 시점의 n값(42)를 기억하고 있다. 이처럼 자유 변수를 포함하는 함수를 `클로저`라고 한다.
#### 클로저 ? 
  - 클로저는 자유변수를 기억하는 함수이다. 자유변수란 함수 바깥 스코프에 선언된 변수이지만, 그 함수 안에서 사용되는 변수이다.
  - 클로저는 내부 함수가 외부 함수의 변수를 자기 안에 포획해서 기억하는 현상이다.
  - 클로저의 작동원리
    - 1. 내부함수가 외부함수에 정의되어야 한다.
    - 2. 내부 함수가 외부 함수의 변수를 참조해야 한다.
    - 3. 외부 함수가 내부 함수를 반환해야 한다.

```py
def outer_function(x):
    # x는 외부 함수의 지역 변수
    def inner_function(y):
        # y는 내부 함수의 지역 변수
        # x는 외부 함수의 변수지만, 내부 함수에서 사용되므로 '자유 변수'
        return x + y
    return inner_function

# outer_function을 호출하고, 반환된 내부 함수를 변수 'closure'에 할당
closure = outer_function(10)

# closure(20)을 호출하면, inner_function이 실행됩니다.
# 이 때, inner_function은 이미 기억하고 있는 x 값(10)을 사용합니다.
print(closure(20)) # 30

closure = outer_function(10)코드가 실행될 때, outer_functioninner_function을 반환하고 종료된다. 이때 inner_function은 자신이 사용하던 외부변수 x의 값 10을 함께 저장하고 있다. 그래서 outer_function이 끝난 후에도 closure(20)을 호출하면 x + y, 즉 10 + 20을 계산할 수 있게 되는 것

Docstring

독스트링은 함수, 클래스, 모듈 등을 설명하는 문자열이다.
파이썬에는 """세 개의 큰따옴표로 감싸서 객체의 첫 줄에 작성한다

  • 규칙
    • 객체의 목적을 명확하고 간결하게 요약한다.
    • 여러 줄일 경우, 첫 줄과 나머지 설명 사이를 한 줄 띄운다.
    • 첫 줄은 대문자로 시작하고 마침표로 끝낸다.함수 어노테이션
    • 함수 어노테이션은 파이썬 함수가 사용하는 자료형에 대한 추가적인 정보를 제공하는 기능이다.

      함수 어노테이션은 def로 함수를 정의할 때, 매개변수나 반환 값 옆에 콜론(:)화살표(->)를 사용해 자료형을 명시하는 문법이다.
    • def fib(n): """ n보다 작은 피보나치 수열을 출력하는 함수. 피보나치 수열은 앞의 두 항의 합으로 다음 항을 만드는 수열입니다. 예: 0, 1, 1, 2, 3, 5, ... Args: n (int): 피보나치 수열을 생성할 상한값. """ a, b = 0, 1 while a < n: print(a, end=' ') a, b = b, a + b print()
public String f(String ham, String eggs)
  • 자바에서는 위와 같이 함수의 시그니처에 자료형이 필수적으로 포함된다
    def f(ham: str, eggs: str = 'eggs') -> str:
  • 파이썬에서는 이렇게 선택적으로 자료형을 명시할 수 있다.

객체

이터레이터

이터레이터는 특정 프로토콜을 따르는 객체

이터레이터는 특정 자료형의 데이터에 접근하는 행동을 의미한다.

  • 자료형 : 데이터를 담는 그릇
    my_list = [1, 2, 3]
  • 이터레이터 : 그 그릇 안의 데이터를 하나씩 꺼내주는 도구
    my_itereator = iter(my_list)
  • 리스트는 이터러블이기 때문에, iter() 함수를 사용하여 이터레이터 객체를 만들 수 있다. 이렇게 만들어진 객체는 next() 메서드를 가지고 있어서, 요소를 하나씩 순서대로 반환하는 역할을 한다.

기능

f-string

f-string 은 String.format()이나 문자열 결합을 더 쉽고 직관적으로 만들어주는 기능이다.

문자열 앞에 f를 붙이고 문자열 안에 {}중괄호를 사용해 변수나 파이썬 코드를 직접 넣을 수 있게 해준다.

name = "김철수"
age = 30
message = f"제 이름은 {name}이고, 나이는 {age}세입니다."
  • f-string을 사용하면 변수나 표현식을 문자열 안에 바로 넣을 수 있어 코드가 깔끔하고 성능도 뛰어나다.

'Python' 카테고리의 다른 글

[Python] 모듈  (0) 2025.09.25
[Python] 자료구조  (0) 2025.09.25