*args : 가변 아규먼트, 여러가지 인자들을 가변인수로 받음. tuple로 저장
**kwargs : 딕셔너리로 가변인수를 받음.
a, b, *c = 10, 20, 30, 40, 50
print(a) # 10
print(b) # 20
print(c) # (30, 40, 50)
args 패킹
def func(*args):
print(args) # (10, 20, 30)
func(10, 20, 30)
# 10, 20, 30 => *args => (10, 20, 30)
args 언패킹
def func(a, b, c):
print(a, b, c) # 10 20 30
args = (10, 20, 30)
func(*args)
# (10, 20, 30) => *args => 10, 20, 30
kwargs 패킹
def func(a=100, **kwargs):
print(a, kwargs)
func(1000, i=1, j=2, k=3)
# a=1, b=2, c=3 => **kwargs => {'a':1, 'b':2, 'c':3}
kwargs 언패킹
def func(d=100, c=200, b=300, a=400):
print(d, c, b, a)
kwargs = {'a':1, 'b':2, 'c':3}
func(**kwargs)
# func(d = 100, c = 3, b = 2, a = 1) 랑 같음
# {'a':1, 'b':2, 'c':3} => **kwargs => a=1, b=2, c=3
주의할점
# *args뒤에 일반 변수를 선언하지 못함
def print_args(a, b, *args, d):
print(args)
for x in args:
print(x)
print_args(100, True, 'Licat', 'Hello', 10) # Error
def print_args(a, b, *args, *c): # *args뒤에 또다른 가변 아규먼트를 넣지 못함
print(args)
for x in args:
print(x)
print_args(100, True, 'Licat', 'hello', 10) # Error
이터레이터
값을 차례로 꺼내서 쓸 수 있는 객체
반드시 __iter__와 __next__ 매직 메서드 정의해야함.
이터레이터 예시
class MyIterator:
def __init__(self, stop):
self.current_value = 0 # 현재 값
self.stop = stop # 순회를 멈출 값
def __iter__(self):
return self
def __next__(self):
if self.current_value >= self.stop:
raise StopIteration
result = self.current_value
self.current_value += 1
return result
my_iterator = MyIterator(5)
for i in my_iterator:
print(i)
# for을 만나면 __iter__가 실행이 되고, 반복이 시작되면 __next__를 호출함
for문 작동 원리
class MyIterator:
def __init__(self, stop):
self.current_value = 0 # 현재 값
self.stop = stop # 순회를 멈출 값
def __iter__(self):
return self
def __next__(self):
if self.current_value >= self.stop:
raise StopIteration
result = self.current_value
self.current_value += 1
return result
my_iterator = MyIterator(5)
i = iter(my_iterator) # 여기서부터
print(next(i)) # 0
print(next(i)) # 1
print(next(i)) # 2
print(next(i)) # 3
print(next(i)) # 4
print(next(i)) # error # 여기까지가 for 작동 원리
제너레이터
이터레이터를 생성해주는 함수. yield를 이용
yield를 만나면 다음에 다시 호출될 때 까지 기다림.
def my_generator(data):
for i in data:
yield i * 10
for i in my_generator([1, 2, 3]):
print(i)
# 10
# 20
# 30
def my_generator():
x = 10
yield x
x = 20
yield x
x = 30
yield x
for i in my_generator():
print(i)
# 10
# 20
# 30
def my_generator():
count = 1
while True:
yield count
count += 1
print(list(zip(['a', 'b', 'c'], my_generator()))) # [('a', 1), ('b', 2), ('c', 3)]
제너레이터 컴프리헨션
gen = (i for i in range(2, 11, 2))
print(type(gen))
for i in gen:
print(i)
# <class 'generator'>
# 2
# 4
# 6
# 8
# 10
연습문제
# 회전초밥집에 들어갔습니다. 초밥은 아래와 같은 양식으로 나옵니다.
[['광어초밥', 1000], ['연어초밥', 2000], ['계란초밥', 3000]]
# 각 초밥은 몇 개 나올지 알 수 없습니다.
# 각 초밥은 1000원씩 비싸집니다.
# 초밥에 '어'가 나오는 초밥만 먹습니다.
# 내가 먹은 초밥의 비용을 계산하는 코드를 작성해 주세요.
def sushi_gen(data):
for sushi in data:
if '어' in sushi[0]:
yield sushi[1]
def solution(data):
price = 0
for sushi_price in sushi_gen(data):
price += sushi_price
return price
data = [['광어초밥', 1000], ['연어초밥', 2000], ['계란초밥', 3000], ['문어초밥', 4000], ['장어초밥', 5000]]
print(f'내가 먹은 초밥의 총 비용은 {solution(data)}원 입니다')
# 문제1
# 다음과 같이 동작하는 제너레이터 함수 fibonacci(n)를 완성하세요.
# 주어진 숫자 n까지의 피보나치 수열을 반환합니다.
def fib(n):
pre = 1
next = 1
count = 0
while True:
temp = pre + next
yield pre
pre, next = next, temp
count += 1
if count == n:
break
for i in fib(5):
print(i)
'''
출력
1
1
2
3
5
'''
# 문제2
# 주어진 함수의 실행 시간을 측정하여 출력하는 데코레이터 time_it를 작성하세요.
# (힌트: time 모듈의 time() 함수를 사용하세요.)
import time
def time_it(func):
def wrapper():
start_time = time.time()
func()
end_time = time.time()
print(f"{end_time - start_time:.4f}s")
return wrapper
@time_it
def main():
def fib(n):
pre = 1
next = 1
count = 0
while True:
temp = pre + next
yield pre
pre, next = next, temp
count += 1
if count == n:
break
for i in fib(20):
print(i)
main()
'Python' 카테고리의 다른 글
Python(19) 정규표현식 (0) | 2023.09.22 |
---|---|
Python(18) f-string 문법 (0) | 2023.09.21 |
Python(16) 일급 함수와 고차 함수, 클로저, 데코레이터 (0) | 2023.09.20 |
Python(15) 예외 처리와 오류 관리 (0) | 2023.09.19 |
Python(14) 모듈 (0) | 2023.09.19 |