Part1의 1, 2는 환경설정이므로 생략
a = "한글"
b = a.encode('utf-8')
b.decode('utf-8') # 인코딩과 맞춰야 함
소스코드의 인코딩과 디코딩
# -*- coding: utf-8 -*-
함수 안의 함수를 결과로 반환할 때, 그 내부 함수를 클로저라고 함
<사용되는 곳>
콜백 함수
함수의 순차적 실행
데코레이터 함수
받은 수에 n을 곱하고 싶을 때 mul3 mul4.. 함수를 각각 만들기 비효율적
방법1. 클래스 사용
class Mul:
def __init__(self, m):
self.m = m
def mul(self, n):
return self.m * n
def __call__(self, n): # mul 함수를 __call__ 함수명으로 변경
return self.m * n
if __name__ == "__main__":
mul3 = Mul(3)
mul5 = Mul(5)
print(mul3.mul(10))
print(mul5.mul(10))
print(mul3(10))
print(mul5(10))
def mul(m): # 외부 함수
def wrapper(n): # 내부 함수 [클로저]
return m * n
return wrapper
if __name__ == "__main__":
mul3 = Mul(3) # m = 3인 wrapper 함수가 mul3에 저장
print(mul3(10)) # m = 3, n = 10인 wrapper 함수가 실행
함수를 꾸며주는 함수
함수를 인수로 받는 클로저
@
을 이용한 어노테이션으로 사용
<사용되는 곳>
반복되는 작업을 여러 함수에 적용할 경우 ex) 로그 남기기 등
기존 함수를 수정하지 않고 추가 기능을 구현하고 싶을 경우
func1, func2 함수의 내용이 중간 값 val만 다르고 다 동일함
함수 각각 정의하는 경우
import time
def func1(a, b):
start = time.time()
print("함수 실행")
val = a + b
end = time.time()
print("실행 시간: %f 초" % (end - start))
return val
def func2(a, b):
start = time.time()
print("함수 실행")
val = a * b
end = time.time()
print("실행 시간: %f 초" % (end - start))
return val
import time
def func1(a, b):
val = a + b
return val
def func2(a, b):
val = a * b
return val
# 실행 시간 측정 데코레이터
def elapsed(func):
def wrapper(a, b):
print("함수 실행")
start = time.time()
result = func(a, b)
end = time.time()
print("실행 시간: %f 초" % (end - start))
return result
return wrapper
if __name__ == "__main__":
deco1 = elapsed(func1)
deco2 = elapsed(func2)
print(deco1(1, 2))
print(deco2(1, 2))
@
활용import time
def elapsed(func):
def wrapper(a, b):
print("함수 실행")
start = time.time()
result = func(a, b)
end = time.time()
print("실행 시간: %f 초" % (end - start))
return result
return wrapper
@elapsed
def func1(a, b):
val = a + b
return val
@elapsed
def func2(a, b):
val = a * b
return val
if __name__ == "__main__":
print(func1(1, 2))
집합에서 값을 차례대로 꺼낼 수 있는 객체(Object)
for문을 순회할 수 있는 객체
반복 가능 (iterable) 객체에만 사용 가능
한 번 반복하면 다시 사용할 수 없음
for a in [1, 2, 3]:
print(a)
a = [1, 2, 3]
iterator = iter(a) # 반복 가능 객체 변환
print(type(iterator)) # list_iterator
print(next(iterator)) # 원소 출력
for a in iterator:
print(a)
next(iterator)
의 경우
3번 호출까지는 차례로 1, 2, 3 출력되고
4번째 호출 시, iterator 내의 모든 원소를 순회했으므로 StopIteration
에러 발생
next(iterator)
를 원소 개수만큼 호출한 후에 for문
으로 iterator을 순회하려 하면,
한 번 반복 후에는 재사용이 불가능하다는 특징에 의해 아무것도 출력되지 않음
다시 사용하고 싶으면 iterator 다시 선언해줘야 함
이터레이터를 생성해주는 함수
함수가 하나의 고정된 값을 반환하는 것이 아닌 순차적으로 다른 값을 반환하기 원할 때
(상황마다 리턴 값이 다르고 싶을 때 / 리턴하는 시점을 다르게 하고 싶을 때 등)
yield()
기본 사용법
def generator():
yield 'a'
yield 'b'
yield 'c'
g = generator()
print(type(g)) # generator
print(next(g))
이터레이터와 마찬가지로 print(next(g))
첫 번째 호출 -> 'a', 두 번째 호출 -> 'b', 세 번째 호출 -> 'c'
네 번째 호출 -> StopIteration
에러 발생
번호표 받는 식당, 자리 날 때마다 몇 번 고객 입장하세요 안내 하기
def client_count(total_client):
n = 1
for num in range(total_client):
print(f"{n} 번째 고객님 입장하세요.")
n += 1
yield
mygen = client_count(100)
next(mygen) # 호출 시마다 차례로 'n 번째 고객님 입장하세요' 출력됨
이때는 print문이 안에 있고 yield
뒤에는 아무것도 없으므로,
print(next(mygen))
하게 되면 출력문 출력된 뒤 None
까지 출력됨