20260323 오늘의 학습: 튜플 활용 + 함수 심화

Yesol Lee·2026년 3월 23일

COS Python

목록 보기
7/30

어제 학습 요약

  • Python 내장함수 정리 (sorted, enumerate, zip, map, filter, any/all, sum)
  • 6문제 풀이, 1차 정답률 100%
  • 함수 작성에서 하드코딩 없이 일반화 성공 (개선 추세)

오늘 수업 계획

Phase 1 마무리를 향해 남은 두 주제를 진행: 튜플 활용법과 함수 심화(*args, **kwargs, 클로저). 문제 10개로 확인.


학습 내용 정리

1. 튜플(tuple) — 수정 못하는 리스트

# 리스트 — 변경 가능 (mutable)
fruits = ["사과", "바나나", "딸기"]
fruits[0] = "포도"  # OK

# 튜플 — 변경 불가 (immutable)
colors = ("빨강", "파랑", "초록")
colors[0] = "노랑"  # TypeError!

Java에는 튜플이 없어서 생소할 수 있지만, Python에서는 엄청 자주 쓰인다. "이 데이터는 바뀌면 안 돼"라는 의도를 코드로 표현하는 것.

2. 튜플을 쓰는 주요 상황

상황예시
좌표처럼 묶인 데이터pos = (3, 5)
함수에서 여러 값 반환return min_val, max_val
딕셔너리 키로 사용grid[(x, y)] = "벽"
언패킹name, age = ("홍길동", 25)

특히 함수 반환값과 언패킹은 COS Pro에서 거의 매번 나온다.

3. 튜플 핵심 문법

# 생성
t1 = (1, 2, 3)
t2 = 1, 2, 3        # 괄호 없어도 튜플!
t3 = (42,)           # 원소 1개일 때 반드시 콤마!
t4 = (42)            # 이건 그냥 int 42

# 인덱싱/슬라이싱 — 리스트와 동일
t1[0]      # 1
t1[1:]     # (2, 3)

# 스왑 (Java에서는 temp 변수 필요!)
a, b = b, a

# 함수에서 여러 값 반환
def min_max(nums):
    return min(nums), max(nums)

lo, hi = min_max([3, 1, 7, 2])  # lo=1, hi=7

4. 튜플 리스트 + sorted + lambda — COS Pro 단골 패턴

students = [("김철수", 85), ("이영희", 92), ("박민수", 78), ("정수진", 95)]

# 점수 기준 내림차순 정렬
students_sorted = sorted(students, key=lambda x: x[1], reverse=True)

# 1등 언패킹
top_name, top_score = students_sorted[0]

이 조합은 시험에서 정말 자주 나오니까 익숙해져야 한다.

5. Python 동시 할당 — temp 변수 없이 스왑

디버깅 문제에서 나온 포인트. 첫 번째와 마지막 요소를 교환할 때:

# Java 스타일 — temp 필요
first = data[0]
data[0] = data[-1]
data[-1] = first

# Python — 동시 할당이라 한 줄이면 끝
data[0], data[-1] = data[-1], data[0]

Python은 우변을 먼저 전부 평가한 뒤 좌변에 할당하기 때문에 중간 변수가 필요 없다. 디버깅 문제에서 data[0], data[-1] = first, last처럼 같은 순서로 넣으면 아무것도 안 바뀌는 게 함정이었다.

6. 딕셔너리 그룹핑 패턴

# 키가 없으면 빈 리스트 만들고 → append
if grade not in groups:
    groups[grade] = []
groups[grade].append(name)

# 한 줄 버전
groups.setdefault(grade, []).append(name)

수업 중 질문: "dict로 변환해서 keys()로 이름을 꺼내면 안 되나?"
→ 동작은 하지만 불필요한 변환이다. 이미 정렬된 튜플 리스트에서 리스트 컴프리헨션으로 바로 꺼내는 게 깔끔하다: [x[0] for x in sorted_list[:n]]


6. 기본값 매개변수 (Default Parameter)

# Java에서는 오버로딩 2개 만들어야 했지만
# Python은 기본값 하나면 끝
def greet(name, greeting="안녕하세요"):
    return f"{greeting}, {name}님!"

greet("홍길동")              # "안녕하세요, 홍길동님!"
greet("홍길동", "반갑습니다")  # "반갑습니다, 홍길동님!"

7. *args와 **kwargs

# *args — 가변 위치 인자 (튜플로 들어옴)
def add_all(*args):
    return sum(args)

add_all(1, 2, 3, 4)  # 10

# **kwargs — 가변 키워드 인자 (딕셔너리로 들어옴)
def print_info(**kwargs):
    for key, value in kwargs.items():
        print(f"{key}: {value}")

print_info(name="홍길동", age=25)

Java의 int... numbers (가변인자)와 비슷하지만, **kwargs는 Java에 없는 개념이다.

매개변수 순서: 일반 → 기본값 → *args → **kwargs

8. 예약어를 키워드 인자로 넘기기

# class는 Python 예약어라서 직접 쓰면 SyntaxError!
make_tag("Image", "div", class="container")  # 에러!

# 딕셔너리 언패킹으로 우회
make_tag("Image", "div", **{"class": "container"})  # OK!

딕셔너리 키는 문자열이라 예약어 충돌이 없다. **로 언패킹하면 키워드 인자로 넘어간다.

9. nonlocal — 클로저에서 바깥 변수 수정

def create_counter(start=0):
    count = start

    def increment():
        nonlocal count   # "count는 바깥 함수 변수야"
        count += 1
        return count

    return increment
키워드의미
global모듈(파일) 최상위 변수 참조
nonlocal바깥 함수의 변수 참조
아무것도 안 쓰면현재 함수의 지역변수

수업 중 질문: "함수 외부에 변수 안 두고 값을 저장해둘 수 있는 거야?"
→ Python의 클로저(closure)가 이걸 가능하게 한다. 안쪽 함수가 바깥 함수의 변수를 기억하고 있다가, nonlocal을 선언하면 수정까지 할 수 있다. Java에서는 클래스 필드에 저장해야 했던 걸, Python에서는 클로저로 간단하게 처리할 수 있다.

10. 함수를 인자로 넘기기

def apply_all(value, *functions):
    result = value
    for func in functions:
        result = func(result)
    return result

double = lambda x: x * 2
add_ten = lambda x: x + 10
apply_all(3, double, add_ten)  # 3 → 6 → 16

Python에서는 함수도 변수처럼 넘기고 호출할 수 있다.

11. *args + all()로 다중 조건 필터링

def filter_all(items, *conditions):
    result = []
    for item in items:
        if all(condition(item) for condition in conditions):
            result.append(item)
    return result

is_positive = lambda x: x > 0
is_even = lambda x: x % 2 == 0
is_small = lambda x: x < 50

filter_all([-3, 4, 7, 12, -8, 50, 22], is_positive, is_even, is_small)
# → [4, 12, 22]

*conditions로 조건 함수를 여러 개 받고, all()로 모든 조건을 만족하는지 확인하는 패턴. 함수를 인자로 넘기는 것과 *args, all()이 합쳐진 종합 문제다.

리스트 컴프리헨션 버전:

def filter_all(items, *conditions):
    return [item for item in items if all(c(item) for c in conditions)]

12. lambda 루프 함정 — 알아두면 좋은 것

# 이렇게 쓰면 전부 같은 값이 나온다!
multipliers = []
for i in range(1, 4):
    multipliers.append(lambda x: x * i)  # i를 값이 아니라 변수 자체를 기억

# 전부 15 (i가 마지막에 3이 되어있으니까)
print(multipliers[0](5))  # 15!

# 함수로 감싸면 해결
def make_multiplier(n):
    return lambda x: x * n  # n에 그 시점의 값이 복사됨

lambda는 변수를 기억하지, 값을 기억하는 게 아니다. 루프 안에서 직접 쓸 때 주의!


오늘의 결과

  • 10문제 풀이, 1차 정답률 70% (7/10), 최종 전부 정답
  • 튜플 활용 안정적, 함수 심화 개념 빠르게 흡수
  • 다음 시간: Phase 1 마무리 — 예외 처리(try/except) + 종합 복습
profile
문서화를 좋아하는 개발자

0개의 댓글