EST AI Challengers 4일차. 파이썬 함수와 모듈 학습


오늘 배운 내용

함수 정의와 return

def 키워드를 사용하여 코드 덩어리에 이름을 붙이고, 필요할 때마다 재사용할 수 있게 해주는 기능이다. 매번 똑같은 코드를 복사해서 붙여넣기 하는 수고를 덜어준다.

중요한 점은 print()와 return의 차이점이다.

  • print()는 단지 화면에 결과값을 보여주기만 할 뿐, 변수에 할당하면 None이 저장된다. 함수 밖으로 값을 반환하지 않는다.

  • 반면 return은 계산 결과를 함수 밖으로 돌려주어 다른 코드에서 재사용할 수 있게 해주고, 함수는 return을 만나는 즉시 종료된다.

  • 함수 매개변수에 기본값을 지정해두면 호출 시 인자를 생략해도 기본값이 들어간다. 이때 기본값이 있는 매개변수는 반드시 기본값이 없는 매개변수 뒤에 위치해야 한다.

  • 값을 반환할 때 return a, b처럼 콤마로 나열하면 튜플로 묶여서 여러 값을 한 번에 반환할 수 있다.

lambda 함수

def로 이름까지 지어가며 정의하기 번거로울 때 사용하는 이름 없는 한 줄 함수 즉, 무명함수이다.

  • lambda 매개변수: 표현식 형태로 작성하며, return 키워드를 쓰지 않아도 표현식의 결과가 자동으로 반환된다.

  • 여러 줄의 복잡한 로직은 담을 수 없지만, 리스트나 딕셔너리를 정렬할 때 .sort(key=lambda x: x[1])처럼 기준(key)을 잡아주는 용도로 아주 유용하게 쓰인다.

  • 람다 안에서도 if...else를 활용한 조건부 표현식을 중첩해서 사용할 수 있지만 else를 빼먹으면 문법 오류가 나니 반드시 세트로 써야 한다.

map과 filter

리스트 안의 데이터들을 일괄적으로 변환하거나 조건에 맞게 걸러낼 때 사용하는 전용 함수이자 객체들이다.

  • map(함수, 반복대상)은 리스트의 모든 요소에 동일한 함수 연산을 적용한다.
  • filter(조건함수, 반복대상)은 조건함수가 True를 반환하는 값만 남기고 나머지는 걸러낸다.
  • 주의할 점은 이 두 함수의 결과값이 리스트와 같은 자료형이 아니라 1회용 객체라는 것이다. 따라서 결과를 재사용하거나 눈으로 확인하려면 반드시 list()로 한 번 감싸서 리스트 자료형으로 변환해야 한다.

내장함수

자주 쓰이는 기능이라 파이썬이 이미 만들어 제공하는 함수들이다. 그렇기에 내장함수를 쓴다면 일일이 for문을 돌려 계산할 필요가 없다.

  • 합계 sum(), 최댓값 max(), 최솟값 min(), 길이 len(), 절댓값 abs(), 반올림 round() 등을 지원한다.

  • 리스트 중 하나라도 참이면 True를 반환하는 any()와, 모든 값이 참이어야 True를 반환하는 all()이 있고 빈 리스트의 경우 any([])는 False, all([])는 True가 나오니 이 부분은 유의해야 한다.

  • .sort()는 원본 리스트 자체의 순서를 바꾸고 None을 반환하지만, sorted()는 원본은 그대로 둔 채 정렬된 새 리스트를 반환하기에, 튜플은 값이 바뀌지 않으므로 .sort()는 못 쓰고 sorted()만 사용 가능하다.

표준 모듈

미리 만들어진 강력한 코드 묶음을 import 키워드로 불러와서 사용하는 방법이다.

  • math 모듈: 원주율(pi), 제곱근(sqrt), 내림(floor), 올림(ceil), 팩토리얼(factorial)

  • random 모듈: 무작위 값을 다룬다. randint (범위 내 정수), choice (목록 중 하나 뽑기), sample (중복 없이 여러 개 뽑기), shuffle (순서 섞기)

  • datetime 모듈: 현재 시각을 구하는 datetime.now()와, 원하는 날짜 형식으로 출력하는 strftime() 메서드

  • 불러올 때는 전체를 가져오는 import math, 특정 기능만 콕 집어오는 from math import pi, 별칭을 붙이는 import pandas as pd 등 상황에 따라 알맞은 방식을 선택할 수 있다.


실습 코드

오늘 배운 함수, 람다, map/filter, 모듈을 종합해서 복습하는 차원에서 간단하게 학생 성적 및 이벤트 관리기를 만들어보며 복습해보았다.

import math
import random
from datetime import datetime

def analyze_scores(scores, pass_mark=60):
    total = sum(scores)          # 내장함수 sum 활용
    avg = total / len(scores)    # 내장함수 len 활용
    passed = len(list(filter(lambda x: x >= pass_mark, scores))) # filter, lambda
    return total, avg, passed    # 여러 값을 튜플로 반환

student_scores = [85, 42, 90, 55, 78]
total, average, pass_count = analyze_scores(student_scores)

print(f"총점: {total}, 평균: {average}, 합격자 수: {pass_count}")

# 내장함수, map, lambda 
adjusted_scores = list(map(lambda x: round(x * 1.1, 1), student_scores)) # 내장함수 round 
print(f"보정된 점수: {adjusted_scores}")

print(f"최고점: {max(adjusted_scores)}, 최저점: {min(adjusted_scores)}")
print(f"모두가 50점 이상인가?: {all(s >= 50 for s in adjusted_scores)}") # 내장함수 all

print(f"점수 내림차순(원본유지): {sorted(adjusted_scores, reverse=True)}")
print(f"원본 리스트 상태: {adjusted_scores}") # 원본은 그대로

# random과 datetime (이벤트 당첨자 뽑기)
students = ["철수", "영희", "민수", "지훈", "수진"]
winner = random.choice(students)               # 1명 무작위 추첨
lotto_nums = random.sample(range(1, 46), 6)    # 중복 없이 6개 추첨

now = datetime.now()
print(f"\n[{now.strftime('%Y년 %m월 %d일')} 추첨 이벤트 결과]")
print(f"오늘의 행운의 학생: {winner}")
print(f"추천 로또 번호: {sorted(lotto_nums)}")

오늘의 회고

1. 배운 점

  • 1회용 map/filter 객체: map이나 filter를 쓰고 나서 list()로 감싸지 않으면 엉뚱한 메모리 주소값(<map object at...>)만 출력되고, 한 번 쓰면 내용물이 사라지는 객체라는 점이 신기했다.

2. 어려운 점 / 개선할 점

  • lambda 함수 안에 여러 개의 조건을 넣으려고 if...else를 중첩하다 보니 코드가 엄청나게 길어지고 읽기 힘들어졌다. 람다는 정말 짧고 간단할 때만 써야지, 복잡해지면 그냥 마음 편히 def로 빼는 게 맞겠다는 생각이 들었다.

3. 액션 플랜

  • ✅ map()과 filter()를 사용할 때 습관적으로 list()로 감싸는 연습하기
  • ✅ .sort()를 변수에 담고 왜 None이 나오는지 당황하지 않기
  • ⬜ import math와 from math import pi의 차이를 이해하고 내 코드 스타일에 맞춰 일관성 있게 사용하기

4. 함께 나누고 싶은 점

  • 공유하고 싶은 팁: Pandas 데이터 전처리 과정에서 apply() 함수가 오늘 배운 map()과 매우 똑같은 원리로 작동한다고 하니 오늘 배운 map과 filter의 사고방식을 잘 다져두면 나중에 데이터 분석 라이브러리를 배울 때 훨씬 수월할 것 같다!

  • 오늘의 고민과 해결: 모듈을 불러올 때 기능이 10개 이상으로 많아지면 어떻게 임포트하는 것이 좋을지에 대해 고민해 보았다. 결론부터 말하자면 import math 형태로 전체를 불러오고 math.기능으로 사용하는 것이 가독성과 안전성 측면에서 가장 권장되는 좋은 코드라는 것을 알게 되었다. 출처를 명확히 밝히는 것이 파이썬의 핵심 철학이라고 생각하기 때문이다.


참고자료

학습 예정

  • 데이터 분석 기초