오픈소스기반데이터분석 3강 - 데이터 분석을 위한 파이썬 프로그래밍 (2)
이번 강의에서는 데이터 분석에 유용한 파이썬 문법 요소와 함수형 프로그래밍 기법을 학습한다. 시퀀스 언패킹과 확장 언패킹, 언더스코어, 예외 처리의 흐름을 이해하고, 람다 함수와 map·filter·reduce를 이용해 데이터를 변환·선택·축소하는 방법을 정리한다.
제1장 언패킹의 개념
1. 여러 값을 개별 변수에 나누어 할당하기
언패킹(unpacking)은 리스트, 튜플, 문자열과 같은 시퀀스 자료형에 들어 있는 여러 값을 개별 변수로 분리해 할당하는 기능이다. 하나의 데이터 묶음에서 필요한 요소를 꺼내 각 변수에 직접 연결하므로 인덱스를 반복해서 작성하지 않고도 데이터의 의미를 명확하게 표현할 수 있다.
기본 문법은 할당문의 왼쪽에 여러 변수를 쉼표로 나열하고 오른쪽에 시퀀스 객체를 두는 방식이다. 일반적인 시퀀스 언패킹에서는 왼쪽 변수의 수와 오른쪽 요소의 수가 일치해야 한다.
변수1, 변수2, ..., 변수n = 시퀀스_객체
2. 리스트와 문자열 언패킹
RGB 색상값처럼 세 요소의 의미가 분명한 리스트는 세 변수로 바로 나눌 수 있다. 아래 코드에서 리스트의 첫 번째 요소는 red, 두 번째 요소는 green, 세 번째 요소는 blue에 순서대로 할당된다.
rgb = [255, 128, 0]
red, green, blue = rgb
print(f"빨강: {red}, 초록: {green}, 파랑: {blue}")
문자열도 문자들이 순서대로 나열된 시퀀스이므로 언패킹할 수 있다. "ABC"를 세 변수에 할당하면 각각 "A", "B", "C"가 저장된다.
word = "ABC"
first, second, third = word
시험 핵심: 기본 언패킹은 시퀀스의 요소 순서에 따라 변수에 값을 할당한다. 별표가 없는 경우 변수 개수와 요소 개수가 맞지 않으면 정상적으로 할당할 수 없다.
제2장 확장 언패킹
1. 별표로 나머지 요소 모으기
확장 언패킹은 왼쪽 변수 하나 앞에 별표(*)를 붙여 나머지 여러 요소를 한꺼번에 받는 방식이다. 별표가 붙은 변수에는 해당 위치에서 남는 요소들이 리스트로 모인다. 데이터의 첫 요소와 마지막 요소는 따로 사용하면서 가운데 길이가 달라질 수 있는 구간을 한 변수로 처리할 때 특히 유용하다.
변수1, *나머지변수, 변수n = 시퀀스_객체
2. 월별 판매액 데이터의 분리
12개월 판매액에서 1월과 12월의 값을 따로 얻고 2월부터 11월까지를 묶으려면 다음과 같이 작성할 수 있다. first에는 첫 요소, last에는 마지막 요소, middle에는 그 사이의 모든 요소가 리스트로 저장된다.
monthly_sales = [1200, 1350, 1420, 1500, 1300, 1580,
1620, 1700, 1800, 1850, 1900, 2000]
first, *middle, last = monthly_sales
print(first) # 1200
print(middle) # 2월부터 11월까지의 값
print(last) # 2000
확장 언패킹은 데이터 길이가 고정되지 않았더라도 앞·뒤의 핵심 항목과 나머지 항목을 간결하게 분리할 수 있다는 장점이 있다. 다만 하나의 할당문에서 여러 개의 별표 변수를 동시에 사용하면 어느 변수가 몇 개의 요소를 받을지 결정할 수 없으므로 하나만 사용한다.
| 구분 | 형식 | 결과 |
|---|---|---|
| 기본 언패킹 | a, b, c = sequence | 각 요소를 변수 하나씩에 할당한다. |
| 확장 언패킹 | a, *middle, z = sequence | 남는 여러 요소를 middle 리스트에 모은다. |
제3장 언더스코어의 활용
1. 사용하지 않을 값 표시하기
파이썬에서 언더스코어(_)는 값이 필요하지 않음을 나타내는 관례적인 변수 이름으로 사용할 수 있다. 언패킹할 데이터에는 여러 항목이 있지만 일부 항목만 필요하다면, 사용하지 않을 위치에 일반 변수 이름 대신 언더스코어를 배치해 코드의 의도를 드러낼 수 있다.
예를 들어 학생 정보가 학번, 이름, 학과, 학년, 성적 순서로 구성되어 있고 이름과 성적만 필요하다면 다음과 같이 작성할 수 있다.
students = [
(20251234, "김철수", "컴퓨터과학", 2, 3.8),
(20265678, "이영희", "생활과학부", 3, 4.2),
(20243456, "박민수", "사회복지학과", 1, 3.5)
]
for _, name, _, _, grade in students:
print(f"{name}의 성적: {grade}")
2. 반복 횟수만 필요할 때
반복문에서 반복 횟수는 필요하지만 현재 반복값을 본문에서 사용하지 않는 경우에도 _를 반복 변수로 사용한다. 다음 반복문은 range가 만드는 0부터 4까지의 값 자체에는 관심이 없고 같은 문장을 다섯 번 출력하려는 목적을 표현한다.
for _ in range(5):
print("Hello, Data Analysis with Open Source!")
언더스코어도 문법적으로는 일반 변수처럼 값을 받을 수 있다. 다만 해당 값을 이후에 의미 있게 사용하지 않겠다는 의도를 다른 개발자에게 보여 주는 관례로 이해해야 한다.
제4장 예외와 예외 처리
1. 예외 처리의 필요성
프로그램 실행 중에는 잘못된 사용자 입력, 0으로 나누기, 존재하지 않는 파일 열기처럼 예상하지 못한 오류가 발생할 수 있다. 이러한 실행 중 오류를 예외(exception)라고 한다. 예외를 처리하지 않으면 프로그램이 즉시 종료되어 사용자 경험이 나빠지고, 작업 중인 데이터가 손실되거나 파일·연결 같은 리소스가 제대로 정리되지 않을 수 있다.
예외 처리(exception handling)는 오류가 발생할 가능성이 있는 코드를 보호하고, 예외가 발생했을 때 적절한 대응 코드를 실행하여 프로그램의 비정상 종료를 방지하는 기법이다. 파이썬에서는 주로 try-except 문과 finally 블록을 사용한다.
| 구성 요소 | 역할 |
|---|---|
try | 예외가 발생할 가능성이 있는 코드를 실행한다. |
except | 지정한 예외가 발생했을 때 대응 코드를 실행한다. |
finally | 예외 발생 여부와 관계없이 마지막에 반드시 실행한다. |
핵심 목적: 예외 처리는 오류를 숨기는 기능이 아니라, 예상 가능한 오류 상황에 대응하고 프로그램이 통제되지 않은 방식으로 종료되는 것을 막는 기능이다.
제5장 try-except 문의 사용
1. 발생 가능한 예외 구분하기
try 블록에는 정상적으로 실행하고 싶은 코드를 작성하고, except 블록에는 특정 예외가 발생했을 때 수행할 대응을 작성한다. 다음 코드에서 사용자가 0을 입력하면 나눗셈 과정에서 ZeroDivisionError가 발생하므로 해당 except 블록이 실행된다.
try:
number = int(input("숫자를 입력하세요: "))
result = 10 / number
except ZeroDivisionError:
print("0으로 나눌 수 없습니다.")
2. 여러 except 블록
하나의 try 블록에서도 여러 종류의 예외가 생길 수 있다. 숫자로 변환할 수 없는 문자열이 입력되면 int()에서 ValueError가 발생하고, 숫자 0이 입력되면 나눗셈에서 ZeroDivisionError가 발생한다. 예외 유형별로 except 블록을 여러 개 두면 상황에 맞는 메시지와 처리 방식을 적용할 수 있다.
try:
number = int(input("숫자를 입력하세요: "))
result = 10 / number
except ZeroDivisionError:
print("0으로 나눌 수 없습니다.")
except ValueError:
print("유효한 숫자를 입력해야 합니다.")
try 블록에서 예외가 발생하면 그 지점 이후의 try 내부 문장은 실행되지 않고, 일치하는 except 블록으로 제어가 이동한다. 예외가 발생하지 않으면 except 블록은 건너뛴다.
여러 except 블록을 사용하는 이유는 오류 원인별로 대응을 분리하기 위해서이다. 0 입력과 숫자가 아닌 입력은 원인과 안내 메시지가 서로 다르다.
제6장 finally 블록
1. 예외 발생 여부와 관계없이 실행하기
finally 블록은 try에서 예외가 발생했는지, except가 실행되었는지와 관계없이 마지막에 실행된다. 파일 작업 종료 안내, 열린 파일 닫기, 사용한 리소스 정리처럼 성공과 실패 양쪽에서 공통으로 수행해야 하는 작업을 배치하는 데 적합하다.
try:
file = open("data.csv", "r")
content = file.read()
print(content)
except FileNotFoundError:
print("파일을 찾을 수 없습니다.")
finally:
print("파일 작업 종료.")
file.close()
위 강의 예제의 핵심은 파일 읽기 중 예외가 있더라도 finally가 실행되어 작업 종료 절차를 수행한다는 점이다. 실제 프로그램에서는 파일 객체가 정상적으로 생성되었는지 확인한 뒤 닫는 등 상황에 맞게 안전한 정리 코드를 작성해야 한다.
구별: except는 특정 예외가 발생했을 때만 실행되고, finally는 예외 발생 여부와 상관없이 실행된다.
제7장 함수형 프로그래밍의 이해
1. 데이터 변경과 부작용 줄이기
파이썬은 절차적 프로그래밍과 객체지향 프로그래밍뿐 아니라 함수형 프로그래밍 방식도 지원한다. 함수형 프로그래밍은 데이터 변경을 최소화하고 순수 함수(pure function)를 활용하여 부작용(side effect)을 줄이는 것을 목표로 한다.
순수 함수는 같은 입력에 대해 항상 같은 출력을 반환하는 함수이다. 부작용은 함수가 값을 계산해 반환하는 것 이외에 외부 상태를 변경하거나 외부에 영향을 미치는 행위를 말한다. 데이터의 상태 변경과 외부 영향을 줄이면 각 함수의 동작을 독립적으로 이해하기 쉬워진다.
2. 데이터 분석에서의 장점
함수형 방식은 데이터에 적용할 변환 규칙을 함수로 표현하므로 코드의 가독성을 높이고 디버깅을 쉽게 할 수 있다. 또한 작업 사이의 의존성과 상태 변경이 적으면 데이터를 나누어 처리하기 쉬워 병렬 처리에 적합한 구조를 만들 수 있다. 파이썬의 map(), filter(), reduce()는 반복 가능한 객체를 대상으로 변환, 필터링, 누적 연산을 수행하는 대표적인 함수형 도구이다.
| 개념 | 의미 |
|---|---|
| 순수 함수 | 같은 입력에 대해 항상 같은 출력을 반환한다. |
| 부작용 | 값 계산 외에 외부 상태나 환경에 영향을 주는 행위이다. |
| 함수형 처리 | 함수를 중심으로 데이터 변환·선택·축소를 표현한다. |
제8장 람다 함수
1. 이름 없는 간결한 함수
람다 함수(lambda function)는 이름 없이 정의하는 익명 함수이다. 짧은 연산을 한 줄의 표현식으로 작성해 즉시 사용할 수 있으므로 map, filter와 같이 다른 함수에 간단한 처리 규칙을 전달할 때 유용하다.
lambda 매개변수: 표현식
람다 함수의 본문에는 단 하나의 표현식만 허용된다. 표현식의 결과가 자동으로 반환값이 되므로 return 키워드를 사용하지 않는다. 복잡한 여러 단계의 처리가 필요하면 일반적인 def 함수가 더 적합하다.
2. 일반 함수와 람다 함수 비교
def add(x):
return x + 2
add_lambda = lambda x: x + 2
print(add(3)) # 5
print(add_lambda(3)) # 5
두 함수는 같은 입력에 같은 결과를 반환하지만 정의 형식이 다르다. 일반 함수는 이름과 문장 블록을 가지며 return을 사용하고, 람다는 표현식 하나로 결과를 반환한다.
3. 급여 조정 예제
직원별 급여를 10% 인상하는 규칙은 lambda salary: salary * 1.1로 표현할 수 있다. 강의 예제에서는 이 람다를 각 급여에 적용하고 딕셔너리 컴프리헨션을 이용해 조정된 급여 딕셔너리를 만든다.
employees = {
"이지혜": 3000000,
"구민준": 5000000,
"방서연": 4100000
}
adjust_salary = lambda salary: salary * 1.1
updated_salaries = {
name: adjust_salary(salary)
for name, salary in employees.items()
}
제9장 map 함수
1. 모든 요소에 같은 함수 적용하기
map()은 반복 가능한 객체의 모든 요소에 지정한 함수를 하나씩 적용하여 새로운 값을 생성한다. 리스트나 튜플의 각 값을 같은 규칙으로 변환할 때 반복문을 직접 작성하지 않고 처리 과정을 표현할 수 있다.
map(함수, 반복가능객체)
map의 결과는 필요한 경우 list()로 변환해 리스트로 확인할 수 있다. 다음 예제는 섭씨 온도 목록의 모든 요소를 화씨 온도로 바꾼다.
temperature_celsius = [25.6, 27.8, 30.5, 22.3, 28.9, 31.2, 24.7]
celsius_to_fahrenheit = lambda c: (c * 9 / 5) + 32
temperature_fahrenheit = list(
map(celsius_to_fahrenheit, temperature_celsius)
)
각 섭씨 값이 람다 함수의 매개변수 c에 차례로 전달되고, 계산된 화씨 값이 새로운 결과에 포함된다. 원본 목록에서 일부 요소를 고르는 것이 아니라 모든 요소를 같은 규칙으로 변환한다는 점이 map의 핵심이다.
map = 변환: 입력의 각 요소에 함수를 적용해 대응하는 새 값을 만든다.
제10장 filter 함수
1. 조건을 만족하는 요소만 선택하기
filter()는 반복 가능한 객체의 요소 중 지정한 조건을 만족하는 요소만 남긴다. 인자로 받는 조건 함수는 각 요소에 대해 True 또는 False를 반환하며, 결과가 True인 원래 요소만 결과 컬렉션에 포함된다.
filter(조건함수, 반복가능객체)
학생별 이름과 점수가 들어 있는 딕셔너리 목록에서 70점 이상만 남기려면 점수가 70 이상인지 확인하는 람다를 전달할 수 있다.
osda_students = [
{"name": "김지원", "score": 85},
{"name": "이민준", "score": 65},
{"name": "박서연", "score": 90},
{"name": "정현우", "score": 55},
{"name": "최예은", "score": 78}
]
passed_students = list(
filter(lambda student: student["score"] >= 70, osda_students)
)
조건을 통과한 요소는 새 값으로 바뀌는 것이 아니라 기존 학생 딕셔너리 형태 그대로 남는다. 즉 map이 요소를 변환한다면 filter는 조건에 따라 요소를 선택한다.
filter = 선택: 조건 함수가 True를 반환한 원래 요소만 결과에 포함한다.
제11장 reduce 함수
1. 여러 요소를 하나의 값으로 축소하기
reduce()는 반복 가능한 객체의 모든 요소를 누적해 하나의 값으로 축소하는 함수이다. 파이썬의 기본 내장 함수가 아니라 functools 모듈에서 제공하므로 먼저 가져와야 한다.
from functools import reduce
reduce는 첫 번째 요소와 두 번째 요소를 함수에 적용하여 중간 결과를 만든다. 이어서 그 중간 결과와 다음 요소를 같은 함수에 적용하고, 이 과정을 마지막 요소까지 반복해 최종 값 하나를 반환한다.
from functools import reduce
numbers = [1, 2, 3, 4, 5]
total_sum = reduce(lambda x, y: x + y, numbers)
print(total_sum) # 15
위 계산은 먼저 1과 2를 더하고, 중간 결과 3에 다음 값 3을 더한다. 이어서 4와 5도 순차적으로 누적하여 최종 합계 15를 만든다.
| 함수 | 처리 목적 | 결과의 특징 |
|---|---|---|
map() | 모든 요소를 변환 | 각 입력 요소에 대응하는 새 값을 만든다. |
filter() | 조건에 맞는 요소 선택 | True인 원래 요소만 남긴다. |
reduce() | 요소를 누적해 축소 | 여러 요소를 최종 값 하나로 만든다. |
핵심 개념 정리
파이썬 문법 요소
- 언패킹은 시퀀스의 요소를 순서대로 개별 변수에 할당한다.
- 확장 언패킹의 별표 변수는 나머지 여러 요소를 리스트로 모은다.
- 언더스코어는 사용하지 않을 값이나 필요하지 않은 반복 변수를 나타내는 데 활용한다.
- try에는 예외 가능 코드, except에는 예외별 대응, finally에는 항상 실행할 정리 코드를 작성한다.
함수형 프로그래밍
- 순수 함수와 데이터 변경 최소화를 통해 부작용을 줄이는 것을 목표로 한다.
- 람다 함수는 단일 표현식으로 작성하며 표현식의 결과를 자동 반환한다.
- map은 모든 요소를 변환하고, filter는 조건을 만족하는 요소를 선택한다.
- functools의 reduce는 요소를 순차적으로 누적해 하나의 결과로 축소한다.
최종 정리: 3강의 핵심은 데이터 묶음을 간결하게 분해하고, 오류 상황을 통제하며, 데이터 처리 규칙을 함수로 표현하는 것이다. 언패킹으로 구조를 해석하고 try-except-finally로 실행을 보호한 뒤, 람다와 map·filter·reduce를 변환·선택·축소의 목적에 맞게 구별해 사용해야 한다.
예상문제 20선
1. 파이썬의 언패킹에 대한 설명으로 옳은 것은?
정답입니다.
오답입니다. 답안을 다시 선택해 보세요.
정답 및 해설 보기
정답: ④
언패킹은 리스트·튜플·문자열 같은 시퀀스의 요소를 순서대로 여러 변수에 직접 할당한다.
2. red, green, blue = [255, 128, 0] 실행 후 green의 값은?
정답입니다.
오답입니다. 답안을 다시 선택해 보세요.
정답 및 해설 보기
정답: ②
시퀀스 요소가 변수 순서대로 할당되므로 두 번째 변수 green에는 두 번째 요소 128이 저장된다.
3. first, *middle, last = [1, 2, 3, 4, 5]에서 middle의 값은?
정답입니다.
오답입니다. 답안을 다시 선택해 보세요.
정답 및 해설 보기
정답: ①
first와 last가 양 끝 요소를 받고, 별표 변수 middle은 가운데 남은 요소를 리스트로 받는다.
4. 반복 변수의 값을 사용하지 않고 같은 작업을 다섯 번 수행하는 표현으로 가장 적절한 것은?
정답입니다.
오답입니다. 답안을 다시 선택해 보세요.
정답 및 해설 보기
정답: ③
반복값을 본문에서 사용하지 않을 때 언더스코어를 반복 변수로 두어 값이 불필요하다는 의도를 나타낸다.
5. 예외 처리의 주된 목적으로 가장 적절한 것은?
정답입니다.
오답입니다. 답안을 다시 선택해 보세요.
정답 및 해설 보기
정답: ②
예외 처리는 예상 가능한 실행 오류에 대응해 강제 종료와 그로 인한 데이터 손실·리소스 누수 등의 문제를 줄인다.
6. 숫자 0으로 나누려고 할 때 발생하는 예외는?
정답입니다.
오답입니다. 답안을 다시 선택해 보세요.
정답 및 해설 보기
정답: ④
0을 분모로 사용한 나눗셈은 허용되지 않으므로 ZeroDivisionError가 발생한다.
7. int("abc")와 같이 숫자로 바꿀 수 없는 문자열을 정수로 변환할 때 발생하는 예외는?
정답입니다.
오답입니다. 답안을 다시 선택해 보세요.
정답 및 해설 보기
정답: ③
문자열의 형식이 정수 변환에 적합하지 않으므로 ValueError가 발생한다.
8. try-except 문에서 try 블록의 역할은?
정답입니다.
오답입니다. 답안을 다시 선택해 보세요.
정답 및 해설 보기
정답: ①
try에는 정상적으로 시도할 코드를 두며, 예외가 발생하면 일치하는 except 블록으로 제어가 이동한다.
9. 예외 발생 여부와 관계없이 실행되는 블록은?
정답입니다.
오답입니다. 답안을 다시 선택해 보세요.
정답 및 해설 보기
정답: ④
finally는 성공과 실패 양쪽에서 공통으로 필요한 파일 닫기나 종료 안내 같은 정리 작업에 사용한다.
10. 순수 함수에 대한 설명으로 옳은 것은?
정답입니다.
오답입니다. 답안을 다시 선택해 보세요.
정답 및 해설 보기
정답: ①
순수 함수는 입력이 같으면 출력도 같으며 외부 상태에 미치는 부작용을 최소화한다.
11. 람다 함수의 올바른 문법 형식은?
정답입니다.
오답입니다. 답안을 다시 선택해 보세요.
정답 및 해설 보기
정답: ②
람다는 lambda 뒤에 매개변수를 쓰고 콜론 다음에 결과를 계산할 단일 표현식을 작성한다.
12. 람다 함수의 문법적 특징으로 옳은 것은?
정답입니다.
오답입니다. 답안을 다시 선택해 보세요.
정답 및 해설 보기
정답: ③
람다 본문에는 단일 표현식이 오며 그 표현식의 계산 결과가 자동으로 반환된다.
13. (lambda x: x + 2)(3)의 결과는?
정답입니다.
오답입니다. 답안을 다시 선택해 보세요.
정답 및 해설 보기
정답: ①
매개변수 x에 3이 전달되고 표현식 x + 2가 계산되어 5를 반환한다.
14. 반복 가능한 객체의 모든 요소에 같은 함수를 적용해 새 값을 만드는 함수는?
정답입니다.
오답입니다. 답안을 다시 선택해 보세요.
정답 및 해설 보기
정답: ④
map()은 각 입력 요소를 함수에 전달하고 그 결과들로 새로운 값을 생성한다.
15. 점수가 70점 이상인 학생만 선택하려 할 때 가장 알맞은 함수는?
정답입니다.
오답입니다. 답안을 다시 선택해 보세요.
정답 및 해설 보기
정답: ②
filter()는 조건 함수가 True를 반환하는 요소만 남기므로 합격 기준에 맞는 학생 선택에 적합하다.
16. filter()에 전달하는 조건 함수의 역할은?
정답입니다.
오답입니다. 답안을 다시 선택해 보세요.
정답 및 해설 보기
정답: ③
filter()는 조건 함수의 결과가 True인 원래 요소만 결과에 포함한다.
17. reduce()를 사용하기 위해 가져와야 하는 모듈은?
정답입니다.
오답입니다. 답안을 다시 선택해 보세요.
정답 및 해설 보기
정답: ②
reduce는 functools 모듈에서 제공하므로 from functools import reduce로 가져온다.
18. reduce(lambda x, y: x + y, [1, 2, 3, 4, 5])의 결과는?
정답입니다.
오답입니다. 답안을 다시 선택해 보세요.
정답 및 해설 보기
정답: ①
두 값을 더한 중간 결과에 다음 요소를 계속 더하므로 최종 합계 15가 반환된다.
19. map, filter, reduce의 기능 연결로 옳은 것은?
정답입니다.
오답입니다. 답안을 다시 선택해 보세요.
정답 및 해설 보기
정답: ③
map은 모든 요소의 변환, filter는 조건에 따른 선택, reduce는 여러 요소를 하나로 누적·축소하는 기능이다.
20. 섭씨 온도 목록의 모든 값을 화씨로 바꾸는 작업에 가장 적합한 구성은?
정답입니다.
오답입니다. 답안을 다시 선택해 보세요.
정답 및 해설 보기
정답: ④
목록의 모든 요소에 동일한 변환식을 적용해야 하므로 변환 함수를 map()에 전달하는 방식이 알맞다.
댓글
댓글 쓰기