2026. 5. 27. 17:19ㆍKDT/1. Python
# for문 (앞 포스터 이어서)
dic1 = {'no':1, 'userid':'apple', 'name':'김사과', 'hp':'010-1111-1111'}
for i in dic1:
print(i, end=' ') # no userid name hp (키만 복사)
print()
for i in dic1.keys(): # 키만 모여있는 객체가 존재
print(i, end=' ') # no userid name hp (키만 복사)
print()
for i in dic1.values():
print(i, end=' ') # 1 apple 김사과 010-1111-1111 (값만 복사)
print()
for i in dic1:
print(dic1[i], end=' ') # 1 apple 김사과 010-1111-1111
print()
for i in dic1:
print(dic1.get(i), end=' ')
# 1 apple 김사과 010-1111-1111
# key를 통해 value를 가져온다 (없으면 None. None이 싫으면 대체 문자 설정 가능 -> 5일차 dict 함수와 메서드 참고)
print()
for i in dic1.items():
print(i)
# ('no', 1)
# ('userid', 'apple')
# ('name', '김사과')
# ('hp', '010-1111-1111')
for key, value in dic1.items():
print(key, value)
# no 1
# userid apple
# name 김사과
# hp 010-1111-1111
# range() 함수
- 순차적인 정수의 시퀀스(순서가 있는 시퀀스 객체)를 생성하는 데 사용되는 내장 함수
- 주로 for문과 함께 사용
- 일정한 범위 내에서 반복 작업을 수행할 때 유용하게 활용
- range() 함수의 반환값은 range 객체로, 실제 정수 시퀀스를 메모리에 저장하지 않고 범위 정보만 가지고 있음
따라서 필요한 정수 시퀀스는 실제 사용 시에 생성
range([start], stop, [step])
start (선택 사항): 순차적인 범위의 시작 값을 지정합니다. 기본값은 0입니다.
stop: 순차적인 범위의 끝 값을 지정합니다. 생성된 시퀀스는 stop 값 직전까지의 정수를 포함합니다.
step (선택 사항): 순차적인 값을 증가시키는 간격을 지정합니다. 기본값은 1입니다.
# enumerate() 함수
- 반복문을 사용할 때 (인덱스, 값)의 튜플을 반환하는 iterator 생성
(인덱스와 값을 함께 가져오는 내장 함수) - 주로 for문과 사용
- 반복문 내에서 순서를 추적하면서 값과 해당 값의 인덱스를 함께 사용할 때 유용
- iterable(반복 가능 객체) : 리스트, 튜플, 딕셔너리, 문자열 같은 컬렉션 자료형은 반복 가능한 객체로 이터레이터 생성 가능
enumerate(iterable, [start=0])
for e in enumerate('hello', 0):
print(e)
# (0, 'h')
# (1, 'e')
# (2, 'l')
# (3, 'l')
# (4, 'o')
for e in enumerate('hello', 2):
print(e)
# (2, 'h')
# (3, 'e')
# (4, 'l')
# (5, 'l')
# (6, 'o')
list1 = [10, 20, 30, 40]
for e in enumerate(list1):
print(e)
# (0, 10)
# (1, 20)
# (2, 30)
# (3, 40)
list1 = [10, 20, 30, 40]
# (0, 10)
# i, v = (0, 10)
for i, v in enumerate(list1):
print(f'인덱스:{i}, 값:{v}')
# 인덱스:0, 값:10
# 인덱스:1, 값:20
# 인덱스:2, 값:30
# 인덱스:3, 값:40
# 이터러블과 이터레이터⭐
1. Iterable (이터러블)
- for문처럼 반복문에서 사용할 수 있는 모든 객체
- 이터러블한 객체는 for item in 객체 : 구조에서 사용 가능
- 모든 순서 있는 컬렉션(리스트, 튜플, 딕셔너리, 문자열)은 이터러블
- 하지만 모든 이터러블이 순서 있는 것은 아님
(set, dict.keys()는 반복되지만 인덱스가 없음)
2. Iterator (이터레이터)
- 이터러블 객체는 iter() 함수를 사용해 이터레이터로 변경 가능
- 또한 next() 사용하여 값을 하나씩 꺼낼 수 있음
- iterable 생성 -> iter() 사용하여 iterator 로 변경 (안의 값을 순서대로 뽑을 수 있는 상태로 만듦) -> next() 사용하여 딱 한 가지 값을 꺼내 사용 -> next() 반복 사용하면 다음 값을 꺼내 사용 가능
이 과정을 for문이 해주는 것임!
numbers = [10, 20, 30]
# iterable -> iterator로 변경
iterator = iter(numbers)
# next()로 값을 하나씩 꺼냄
print(next(iterator)) # 10
print(next(iterator)) # 20
print(next(iterator)) # 30
# print(next(iterator)) -> 여기서 더 꺼내면 StopIteration 예외 발생. for문에는 오류처리기능이 있음
# zip() 함수
- 여러 개의 iterable 객체를 병렬적으로 묶어주는 내장 함수
- 각 객체로부터 순서대로 하나의 요소씩 가져와 튜플로 묶어주는 iterator 반환
- 주로 여러 개의 리스트나 튜플을 병렬적으로 처리하고자 할 때 사용
zip(iterable1, iterable2, ...)
# range() 안의 숫자가 좋지 않은 코드. 특정 숫자가 코드에 박혀있는 것은 안좋은 코드
li1 = [10, 20, 30]
li2 = ['apple', 'banana', 'orange']
for i in range(0, 3):
print(li1[i], li2[i])
# 10 apple
# 20 banana
# 30 orange
# len() 을 사용하는 것도 좋다
# 하지만 li1, li2의 길이가 달라지게 되면 IndexError 발생가능
# li1의 len에 의존하고 있으므로 안좋은 코드
li1 = [10, 20, 30]
li2 = ['apple', 'banana', 'orange']
for i in range(len(li1)):
print((li1[i], li2[i]))
# (10, 'apple')
# (20, 'banana')
# (30, 'orange')
# li라는 변수 1개만 쓰면 패킹돼서 튜플로 반환
li1 = [10, 20, 30]
li2 = ['apple', 'banana', 'orange']
for li in zip(li1, li2):
print(li)
# (10, 'apple')
# (20, 'banana')
# (30, 'orange')
# continue
- 반복문 안에서 사용
- 현재 반복을 즉시 건너뛰고 다음 반복으로 넘어가도록 하는 제어문
- 예를 들어, 리스트를 순회하면서 특정 값만 건너뛰고 싶을 때 if문과 함께 사용
- 불필요한 코드 실행 피하기 가능
# break
- 반복문 안에서 반복을 즉시 종료시키는 제어문
- break 실행 시 반복문의 조건과 상관없이 해당 반복문을 완전히 빠져나옴
- 주로 특정 조건을 만족하면 더 이상 반복을 진행할 필요가 없을 때 사용
- 불필요한 반복을 줄일 수 있음
# 중첩 반복문
1. 중첩 for문
# 2단부터 9단까지 구구단을 출력하는 프로그램을 작성
# for 문
for i in range(2, 10):
print(f"{i}단")
for j in range(1, 10):
print(f"{i} * {j} = {i * j}")
print()
2. 중첩 while문
# while 문
i = 2
j = 1
while i <= 9:
print(f'{i}단')
while j <= 9:
print(f'{i} * {j} = {i*j}')
j += 1
i += 1
j = 1
print()
# Comprehension (컴프리헨션)
- 리스트, 세트, 딕셔너리 등의 컬렉션을 반복문과 조건문을 사용하여 간단하게 생성하거나 변형하는 방법 중 하나
1. list comprehension (리스트 컴프리헨션)
n = 10
result = [0 for i in range(n)]
print(result) # [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
result = [i for i in range(n)]
print(result) # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
=======================================================
li = [10, 20, 30, 40, 50, 60, 70, 80, 90, 100]
result = [n for n in li]
print(result) # [10, 20, 30, 40, 50, 60, 70, 80, 90, 100]
result = [n*2 for n in li]
print(result) # [20, 40, 60, 80, 100, 120, 140, 160, 180, 200]
=======================================================
li = ['apple', 'banana', 'orange', 'melon']
result = [len(str1) for str1 in li]
print(result) # [5, 6, 6, 5]
# if문이 for문의 오른쪽에 있는 경우
result = [n for n in range(10) if n % 2 == 0]
print(result) # [0, 2, 4, 6, 8]
# for문에서 0을 꺼내고, if문으로 확인 후, True이면 return
# if문이 for문의 왼쪽에 있는 경우
# 양수는 리스트에 그대로 저장하고, 음수는 0으로 변환해서 저장하기
li = [-1, 0, -4, 24, 5, -10, 2, 20]
result = [n if n>0 else 0 for n in li]
print(result) # [0, 0, 0, 24, 5, 0, 2, 20]
# for문에서 -1을 꺼내고, if문에서 조건이 맞으면 -1 return, 틀리면 else 실행
li = []
# 다중 for문
for i in range(1, 4):
for j in range(1, 3):
li.append(i * j)
print(li) # [1, 2, 2, 4, 3, 6]
# list comprehension
li = [i*j for i in range(1, 4) for j in range(1, 3)]
print(li) # [1, 2, 2, 4, 3, 6]
# 다중 for문과 list comprehension 중 다중 for문이 가독성 측면에서 나음
# 이런 comprehension은 잘 안씀
2. set comprehension (세트 컴프리헨션)
li = [1, 2, 3, 4, 5, 2, 3, 4]
unique_numbers = set(li)
print(unique_numbers) # {1, 2, 3, 4, 5}
li = [1, 2, 3, 4, 5, 2, 3, 4]
unique_numbers = {x for x in li}
print(unique_numbers) # {1, 2, 3, 4, 5}
3. dictionary comprehension (딕셔너리 컴프리헨션)
names = ['apple', 'banana', 'orange']
name_lengths = {name:len(name) for name in names}
print(name_lengths) # {'apple': 5, 'banana': 6, 'orange': 6}
# 사용자 정의 함수
- 사용자가 특정 작업을 수행하기 위해 직접 작성한 함수
- 파이썬에는 많은 내장 함수가 있지만 요구사항에 맞게 동작하는 함수를 만들어야할 때가 있음

1. 함수의 동작
- 함수 객체를 메모리에 생성
- 그 함수 객체에 함수명 이름을 붙임
def 함수명(매개변수1, 매개변수2, ...):
# 함수 내용
return 결과값
def hello():
print("안녕하세요")
a = hello # 함수를 복사한 것이 아니라, 같은 함수 객체를 참조하는 이름을 하나 더 생성
a()
hello()
2. 함수 객체
function object
├── 함수 이름
├── 매개변수 정보
├── 실행할 코드 정보
├── 기본값 정보
├── 전역 네임스페이스 정보
└── 클로저 정보 : 함수 안에 함수가 있는 경우
3. 함수 호출 시 메모리에서 일어나는 일⭐
def add(a, b):
result = a + b
return result
x = add(3, 5)
- add 이름이 가리키는 함수 객체 찾음
- 함수 실행을 위한 '새 공간' 생성
- 매개변수 a, b에 값 연결
- 함수 본문 실행
- return 값 반환
- 함수 실행 공간 제거
- 스택 프레임(stack frame) 또는 함수 호출 프레임
(= 이때 맨들어지는 '새 공간')
- 함수 호출 시 생성되는 독립적 실행 공간
- 해당 함수의 매개변수, 지연변수, 반환 주소, 실행 상태 (어디까지 실행했는지 등) 저장하는 구조
- 이 프레임을 stack 형태로 관리 -> 함수가 호출될 때 쌓이고 끝나면 제거
- 이를 통해 변수 충돌 없이 안전하게 실행
# 함수 만들기
1. 매개변수x 반환값x
def func1():
print('처음으로 만드는 함수!')
func1()
func1()
print()
for i in range(5):
func1()
2. 매개변수o 반환값x
def func3(start, end):
sum = 0
for i in range(start, end+1):
sum += i
print(f'{start}부터 {end}까지의 합: {sum}')
func3(1, 10)
func3(1, 100)
3. 매개변수x 반환값o
# ⭐
# 함수 스택을 느낄 수 있는 코드 (LIFO)
def funcA():
print("A 시작")
result = funcB()
print("A 끝")
return result
def funcB():
print("B 시작")
result = funcC()
print("B 끝")
return result
def funcC():
print("C 실행")
return 100
# 실행
value = funcA()
print("최종 결과:", value)
4. 매개변수o 반환값o
def func5(num1, num2):
sum = num1 + num2
return sum
print(func5(10, 5))
temp = func5(4, 3)
print(temp)
# print(func5(10)) # TypeError: func5() missing 1 required positional argument: 'num2'
4-1. 기본값이 설정된 매개변수
def func6(num1=0, num2=0):
sum = num1 + num2
return sum
print(func6())
print(func6(10))
print(func6(10, 3))
# print(func6(, 3)) # SyntaxError: invalid syntax
# print(func6(None, 3)) # TypeError: unsupported operand type(s) for +: 'NoneType' and 'int'
print(func6(num2=3)) # num2만 보내고 싶을 경우 지정해서 매개변수 넣어주면 됨
def add_item(item, items=[]):
items.append(item)
return items
print(add_item("사과"))
print(add_item("바나나"))
print(add_item("오렌지"))
# ['사과']
# ['사과', '바나나']
# ['사과', '바나나', '오렌지']
- items=[] 처럼 컬렉션 초기화를 매개변수에 하지 마라
- 함수가 호출될 때마다 새로 만들어지는 것이 아니라 함수 객체가 만들어질 때 한 번 생성
- 모든 호출이 같은 리스트 공유 (items는 stack이 아닌 heap에 올라가게됨)
- 함수는 무조건 실행할 때마다 처음부터 실행되는 것처럼 만들기 (과거에 얽히면 독립적 실행이 어려움)
- print 결과에 사과, 바나나가 누적되는 이유는 items가 살아있기 때문
# 안전하게 사용하는 방법
def add_item(item, items=None):
if items is None:
items = []
items.append(item)
return items
print(add_item("사과"))
print(add_item("바나나"))
print(add_item("오렌지"))
# ['사과']
# ['바나나']
# ['오렌지']
# None
- 값이 존재하지 않음을 나타내는 특별한 객체
- 모든 None 비교 시 == 대신 is 사용 권장
- 함수에서 return 명시하지 않으면 자동으로 None
- False로 평가되지만 (), "", [] 등과는 의미적으로 구분되며,
연산 대상이 아니기 때문에 산술 연산에 사용 불가
5. 가변 매개변수
def func7(*args):
return args
print(func7()) # ()
print(func7(10)) # (10,)
print(func7(10, 30, 50)) #(10, 30, 50)
def func8(a, b, c):
return a + b + c
print(func8(10, 20, 30)) # 60
numbers = [1, 2, 3]
print(func8(*numbers)) # 6
# print(func8(numbers)) # TypeError: func8() missing 2 required positional arguments: 'b' and 'c'
# [1, 2, 3] 이 a로 들어가니까 b, c가 없으므로 에러
6. 키워드 매개변수
def func9(id, name, age):
print(f'아이디: {id}')
print(f'이름: {name}')
print(f'나이: {age}')
func9(age=30, id='orange', name='오렌지')
# ⭐
# 매개변수명과 딕셔너리의 키가 같아야함
# 딕셔너리의 키는 반드시 '문자열' 형태
dic1 = {'age':25, 'id':'banana', 'name':'반하나'}
func9(**dic1)
# *의 데이터를 보낼 경우 키가 저장
func9(*dic1)
7. 여러 개의 반환 값
def func10(num1=0, num2=0):
return num1+num2, num1-num2, num1*num2, num1/num2
result = func10(10, 3)
print(result) # (13, 7, 30, 3.3333333333333335) 패킹돼서 tuple로 출력
result1, result2, result3, result4 = func10(10, 3) # 언패킹도 가능
print(f'덧셈:{result1}')
print(f'뺄셈:{result2}')
print(f'곱셈:{result3}')
print(f'나눗셈:{result4}')
_, _, result3, _ = func10(10, 3) # 원하는 것만 가능
print(f'곱셈: {result3}')
print(f'언더스코어: {_}') # 누적되기 때문에 마지막 것을 반환. 언더스코어는 메모리에 항상 존재하고 있음
_, _, result3, result4 = func10(10, 3)
print(f'곱셈: {result3}')
print(f'나눗셈: {result4}')
li1 = [10, 20, 30, 40, 50]
for _, v in enumerate(li1):
print(f'값: {v}')
# 변수의 범위
1. 지역변수
- 가장 내부의 범위
- 함수 내에서 정의된 변수들이 해당됨
- 함수 내에서만 접근 가능
2. 전역변수
- 스크립트 전체에서 사용되는 범위
- 함수 외부에 정의된 변수가 해당됨
- 모든 함수에서 접근 가능하지만 함수 내부에서 수정하려면 global 키워드 사용
global_var = 10
def modify_global():
global global_var # global 키워드
global_var = 20
modify_global()
print(global_var) # 20
* range()는 사용되고 가비지컬렉터가 지워버리므로 메모리 아낄 수 있음
* iterable과 iterator의 완벽한 이해를 하려면 클래스, 객체지향 등 다른 내용이 필요
- iterable은 여러 자료를 담을 수 있고 (리스트, 튜플, 딕셔너리, 문자열) 반복 가능
- 후에 더 깊게 학습할 예정. 지금은 이정도만 알고 있자
* 예제를 외우지 말고 '로직'을 그려보자 -> 그 후 소스코드를 보지 않고 작성해보기
* 함수를 사용하는 이유는 반복된 과정을 재사용하기 위함
[수업후기]
- enumerate() 함수는 처음 보았다. 반복문에서 잘 활용하면 편리할 것 같다.
- iterable 객체에 리스트, 튜플, 딕셔너리, 문자열이 포함되는 것은 알고 있었고
iterator의 존재도 알고 있었으나 저런 용도로 쓰이는 지는 처음 알았다.
- zip() 함수 길이가 다르다고 에러나거나 한 쪽만 돌아가지 않는다는 것과
여러 개의 반환 값에서 C, Java보다 Python이 발전한 언어라는 것을 느낄 수 있었다.
- 대학 수업에서 처음 반복문을 수강할 때 별 찍는 문제를 풀었었는데, 그 때 조금 헷갈려했던 기억이 있다. 앞으로 어려운 내용들이 나오더라도 지금의 내가 중첩반복문을 보는 것처럼 쉽게 느껴지는 때가 오겠지.
- 리스트 컴프리헨션 이름은 처음 들었지만, 코딩테스트 준비할 때 봤던 내용이고 문제들에 굉장히 자주 쓰였던 아이였다..!
세트, 딕셔너리 컴프리헨션도 있구나
- 키워드 매개변수에서 매개변수명과 딕셔너리의 키가 같으면 출력해주는 것? 정말 멋지다
- 아스테리스크(Asterisk) * 기호의 개수 신경써야겠다. 한 끝 차이로 출력이 달라지니까
- 파이썬에만 있는 함수들을 알려주시면서 수업하셔서 그 부분에서는 좀 더 귀 기울이게 된다. 신기하고 재밌으니까. 그리고 다른 구닥다리 언어들과 차이도 느낄 수 있어서 좋다.
- 5일차 포스팅까지는 그냥 코드들 한 두개 빼고는 다 넣었었는데, 너무 간단하거나 전에도 많이 봤던 예제들까지 적어둘 필요는 없어보여서 오늘부터 걸러서 정리해보았다.
'KDT > 1. Python' 카테고리의 다른 글
| [8일차] 객체지향 프로그래밍(다형성), 예외, 매직메서드 (0) | 2026.05.29 |
|---|---|
| [7일차] 사용자정의함수, 객체지향프로그래밍(캡슐화, 상속) (0) | 2026.05.28 |
| [5일차] 컬렉션 타입(튜플, 세트, 딕셔너리), 제어문(조건문, 반복문) (0) | 2026.05.26 |
| [4일차] 입출력, 연산자, 컬렉션타입(리스트) (0) | 2026.05.26 |
| [3일차] 변수, 자료형, 문자열 다루기 (0) | 2026.05.21 |