Functions. & Module Control of Flow

1. 함수(Function) – “코드를 이름 붙여서 재사용하기”

1-1. 함수가 뭔데?

  • 반복해서 쓰는 코드 덩어리
    이름을 붙여서 모아 놓은 것.
  • 한 번 정의해 두면 여러 번 호출해서 재사용할 수 있음.
  • “입력 ➜ 처리 ➜ 출력”을 한 덩어리로 묶은 느낌.
def add(a, b):      # add 라는 이름의 함수 정의
    result = a + b  # 처리
    return result   # 결과 돌려주기

print(add(3, 5))    # 함수 호출 => 8

이렇게 해 두면, 3+5, 10+20, 100+200… 매번 코드를 새로 쓰지 않고 add()만 계속 호출하면 됨.


1-2. 함수 기본 구조

함수는 항상 이 네 가지 구성을 가진다고 생각하면 편함.

def 함수이름(매개변수들):
    """여기에 함수 설명(Docstring)을 작성한다."""
    # 함수 본문(body) – 실제로 일하는 코드
    ...
    return 결과값
  1. def 키워드
  2. 함수 이름
  3. 괄호 안 매개변수(parameter)
  4. 함수 몸통(body) + return (선택)

1-3. 함수 호출하기

정의만 해두면 아무 일도 안 일어남.
“이제 일해줘!”라고 시키려면 호출(call) 해야 함.

def greet(name):
    print(f"{name}님 안녕하세요!")

greet("혜령")   # 여기서 실제로 함수가 실행됨
greet("홍길동")

2. return vs print – 진짜 자주 헷갈리는 포인트

2-1. return은 “값을 돌려주기”

def square(x):
    return x * x

result = square(3)
print(result)  # 9
  • return은 함수 밖으로 값을 돌려주는 역할.
  • return을 만나면 함수는 그 즉시 종료됨.
  • 돌려준 값은 변수에 담거나, 다른 계산에 바로 쓸 수 있음.

2-2. print는 “눈에 보여주기”

def square_and_print(x):
    print(x * x)

result = square_and_print(3)
print("result:", result)  # result: None
  • print콘솔에 글자를 찍는 것일 뿐,
  • 함수의 “결과값”이 아님.
  • 아무 return이 없으면 기본적으로 None을 돌려줌.

정리

  • “계산 결과를 다시 써먹고 싶다” → return
  • “그냥 화면에 보여주기만 하면 된다” → print

3. 매개변수(Parameter)와 인자(Argument)

3-1. 용어 정리

  • 매개변수(parameter)
    • 함수를 정의할 때 괄호 안에 적는 이름
    • 함수 안에서 쓰는 변수 역할
  • 인자(argument)
    • 함수를 호출할 때 실제로 넣어주는 값
def add(a, b):      # a, b  → 매개변수(parameter)
    return a + b

add(3, 5)           # 3, 5 → 인자(argument)

3-2. 다양한 인자 종류

1) 위치 인자(Positional Arguments)

  • 순서대로 매개변수에 값이 들어감.
  • 기본적인 호출 방식.
def greet(name, age):
    print(f"{name}은 {age}살입니다.")

greet("Alice", 25)   # name="Alice", age=25

2) 기본값 인자(Default Arguments)

  • 매개변수에 기본값을 미리 정해둘 수 있음.
  • 안 넣으면 기본값, 넣으면 넣은 값 사용.
def greet(name, age=20):
    print(f"{name}은 {age}살입니다.")

greet("Bob")         # Bob은 20살입니다.
greet("Charlie", 30) # Charlie는 30살입니다.

3) 키워드 인자(Keyword Arguments)

  • 매개변수이름=값 형태로 전달.
  • 순서와 상관없이 알맞은 매개변수에 들어감.
def greet(name, age):
    print(f"{name}은 {age}살입니다.")

greet(age=30, name="Dave")

4) 가변 위치 인자 *args

  • 인자의 개수를 유동적으로 받고 싶을 때.
  • 함수 안에서 tuple로 사용.
def add_all(*numbers):
    print(numbers, type(numbers))  # (1, 2, 3) <class 'tuple'>
    return sum(numbers)

print(add_all(1, 2, 3, 4))

5) 가변 키워드 인자 **kwargs

  • 키=값 형태의 인자를 여러 개 받을 때.
  • 함수 안에서 dict로 사용.
def print_info(**info):
    print(info)

print_info(name="혜령", age=25, city="Daegu")
# {'name': '혜령', 'age': 25, 'city': 'Daegu'}

6) 섞어서 쓸 때 순서 규칙

항상 이 순서를 지켜야 함:

일반 위치 인자 → args → 기본값 인자 → *kwargs

def func(pos1, *args, default_arg=0, **kwargs):
    ...

4. 재귀 함수(Recursive Function)

4-1. 개념

  • 함수 안에서 자기 자신을 다시 호출하는 함수.
  • 큰 문제를 같은 형태의 더 작은 문제들로 쪼개어 해결할 때 사용.

4-2. 핵심: “기저 사례(Base Case)”가 꼭 있어야 함

  • 무한히 자기 자신을 부르면 프로그램이 끝나지 않고 오류 남.
  • “여기까지 오면 더 이상 재귀 호출을 안 한다” 라는 조건을 꼭 넣어야 함.

4-3. 예시: 팩토리얼 n!

n! = n * (n-1) * (n-2) * ... * 1

재귀 정의:

  • 0! = 1
  • n! = n * (n-1)! (n > 0 일 때)
def factorial(n):
    if n == 0:          # 기저 사례
        return 1
    return n * factorial(n - 1)

print(factorial(5))     # 120
  • 함수가 호출될 때마다 n이 1씩 줄어들다가 0이 되면 재귀 종료.

5. 스코프(Scope)와 LEGB 규칙

5-1. 스코프란?

  • 변수 이름을 찾는 범위.
  • “어디까지 이 변수 이름을 알아볼 수 있냐?”의 문제.

5-2. 파이썬의 스코프 4단계 (LEGB)

이 순서대로 변수를 찾음:

  1. L – Local: 현재 함수 내부
  2. E – Enclosing: 바깥 함수(중첩 함수에서)
  3. G – Global: 모듈(파일) 전체
  4. B – Built-in: 파이썬이 원래 가지고 있는 이름들 (len, sum 등)
x = "global"

def outer():
    x = "enclosing"

    def inner():
        x = "local"
        print(x)

    inner()

outer()  # 'local'

내부에서 이름을 찾을 때는 가까운 스코프부터 먼 스코프 순으로 찾는다고 이해하면 됨.


5-3. global 키워드

  • 함수 안에서 전역 변수 값을 바꾸고 싶을 때 사용.
count = 0

def increase():
    global count
    count += 1

increase()
print(count)  # 1
  • 너무 많이 쓰면 코드 이해하기 힘들어짐 → 가능한 한 지역 변수와 return 값으로 처리하는 습관 들이기.

6. 함수 스타일 & 단일 책임 원칙

6-1. 함수 이름 짓기

  • 소문자 + 언더스코어(snake_case)
    • get_username, calculate_total_price
  • 이름만 봐도 무슨 일을 하는지 알 수 있게 짓기.
def calc_total_price(price, tax):
    return price + tax

6-2. 단일 책임 원칙(Single Responsibility Principle)

한 함수는 한 가지 일만 하도록.

나쁜 예 (여러 일을 한 함수에 다 우겨 넣은 경우):

def handle_user_signup(user_data):
    # 1) 입력 검증
    # 2) DB 저장
    # 3) 이메일 발송
    # 4) 로그 기록
    ...

좋은 방향:

  • validate_user_data
  • save_user
  • send_welcome_email
  • log_signup

처럼 여러 개의 작은 함수로 나누기.
테스트도 쉽고, 유지보수도 쉬워짐.


7. Packing & Unpacking (*, **)

7-1. 패킹(Packing)

  • 여러 값을 하나의 변수에 묶어서 담기.
packed = 1, 2, 3, 4
print(packed)        # (1, 2, 3, 4)  튜플

가변 인자에서의 패킹:

def my_func(*args):
    print(args)

my_func(1, 2, 3)     # (1, 2, 3)

7-2. 언패킹(Unpacking)

  • 묶여 있는 값을 다시 여러 변수로 풀기.
a, b, c = (1, 2, 3)
print(a, b, c)  # 1 2 3

*를 이용한 언패킹:

numbers = [1, 2, 3, 4, 5]
first, *middle, last = numbers
print(first)   # 1
print(middle)  # [2, 3, 4]
print(last)    # 5

딕셔너리도 **로 언패킹해서 함수 인자로 넘길 수 있음.

def introduce(name, age):
    print(name, age)

data = {"name": "혜령", "age": 25}
introduce(**data)   # introduce(name="혜령", age=25)

8. 모듈(Module) – 파일 단위로 코드 묶기

8-1. 모듈이란?

  • 하나의 .py 파일 = 하나의 모듈.
  • 여러 함수를 파일로 묶어놓은 것.
  • 다른 파일에서 가져다 쓸 수 있음.
# my_math.py
def add(a, b):
    return a + b
# main.py
import my_math

print(my_math.add(3, 5))

8-2. import 사용법

  1. 기본 import
import math

print(math.pi)
print(math.sqrt(9))
  1. from ~ import ~
from math import sqrt, pi

print(pi)
print(sqrt(9))
  1. 별칭 붙이기
import math as m
print(m.sqrt(16))

8-3. 사용자 정의 모듈 만들기

  1. 새 파일에 함수/변수 정의
  2. 같은 폴더에서 import 해서 사용
# utils.py
def greet(name):
    print(f"Hello, {name}!")

# main.py
import utils

utils.greet("혜령")

9. 패키지(Package) – 폴더 레벨 묶음

  • 모듈 여러 개를 모아둔 폴더 개념.
  • 보통 이런 구조:
my_package/
    __init__.py
    math_tools.py
    string_tools.py

사용 예시:

from my_package import math_tools

math_tools.add(1, 2)

10. 외부 패키지와 pip

10-1. pip란?

  • 파이썬에서 외부 라이브러리를 설치해주는 도구.
pip install requests
pip install SomePackage==1.2.3

10-2. 설치 후 사용 예

import requests

response = requests.get("https://example.com")
print(response.status_code)

11. 제어문(Control Statement) – 조건과 반복

11-1. 조건문 if / elif / else

score = int(input("점수 입력: "))

if score >= 90:
    print("A")
elif score >= 80:
    print("B")
else:
    print("C 이하")
  • 위에서부터 차례대로 조건을 검사.
  • True인 첫 번째 블록만 실행되고 나머지는 무시.

11-2. 반복문 for

  • 반복 가능한(iterable) 객체의 각 요소를 하나씩 꺼내며 반복.
students = ["Alice", "Bob", "Charlie"]

for student in students:
    print(student)

range()와 함께 쓰기:

for i in range(5):  # 0,1,2,3,4
    print(i)

딕셔너리 순회:

my_dict = {"a": 1, "b": 2}

for key in my_dict:
    print(key, my_dict[key])

11-3. 반복문 while

  • 조건이 참인 동안 반복.
n = 1

while n <= 5:
    print(n)
    n += 1
  • 조건이 언젠가 False가 되도록 코드를 써야 함 (무한 루프 주의).

12. 반복 제어: break, continue, pass

12-1. break – 반복문 강제 종료

for n in range(1, 11):
    if n == 5:
        break
    print(n)    # 1 2 3 4 까지만 출력

12-2. continue – 이번 회차만 건너뛰기

for n in range(1, 6):
    if n % 2 == 0:
        continue
    print(n)   # 홀수만 출력: 1 3 5

12-3. pass – “아직 할 일 없음”

def todo():
    pass  # 나중에 구현할 예정

for _ in range(3):
    pass  # 자리만 만들어 둠

13. map, zip, enumerate – 자주 쓰이는 내장 함수

13-1. map(function, iterable)

  • 각 요소에 함수를 적용해서 새 시퀀스를 만드는 도구.
numbers = [1, 2, 3, 4]

def square(x):
    return x * x

result = list(map(square, numbers))
print(result)  # [1, 4, 9, 16]

람다와 함께 자주 사용:

result = list(map(lambda x: x * x, numbers))

13-2. zip(*iterables)

  • 여러 시퀀스를 같은 인덱스끼리 묶어주는 함수.
names = ["A", "B", "C"]
scores = [100, 90, 80]

for name, score in zip(names, scores):
    print(name, score)
# A 100
# B 90
# C 80

13-3. enumerate(iterable, start=0)

  • 반복하면서 인덱스와 값을 같이 받고 싶을 때.
fruits = ["apple", "banana", "cherry"]

for idx, fruit in enumerate(fruits, start=1):
    print(idx, fruit)
# 1 apple
# 2 banana
# 3 cherry

마무리 정리

  • 함수는 반복되는 작업을 이름 붙여서 재사용하는 도구.
  • return은 값을 돌려주는 것, print는 보여주기만 하는 것.
  • 매개변수/인자 개념 구분 & 위치·기본값·키워드·가변 인자까지 이해하기.
  • 재귀 함수는 항상 기저 사례를 넣어서 종료 조건 만들기.
  • 변수 이름을 찾는 순서는 LEGB.
  • 한 함수에는 한 가지 일만 – 단일 책임 원칙.
  • 모듈은 파일, 패키지는 폴더. import / from ~ import ~ 자유자재.
  • 조건문/반복문으로 흐름을 제어하고, break/continue로 흐름 세밀하게 조정.
  • map, zip, enumerate자료구조를 우아하게 다루는 삼신기 느낌으로 익혀두기.

'Language& Framework > Python' 카테고리의 다른 글

OOP  (1) 2025.12.12
Data Structure  (0) 2025.12.12
Python Basic Syntax  (0) 2025.12.11
myoskin