1. 이터레이터 (iterator)
컬렉션의 요소를 하나씩 순회할 수 있는 객체이다.
iterable과 함께 사용되며 반복 과정을 제어한다.
1.1 이터러블(Iterable)과 이터레이터(Iterator)
1.1.1 이터러블(Iterable)
반복 가능한 객체로, __iter__() 메소드를 구현한 객체.
예를 들어, 리스트, 튜플, 딕셔너리, 문자열 등이 이터러블이다..
1.1.2 이터레이터(Iterator)
__iter__()와 __next__() 메소드를 구현한 객체.
이터레이터는 이터러블의 요소를 순차적으로 반환한다..
- __iter__(self)
- 이터레이터 객체 자체를 반환한다. 이는 반복을 초기화하거나 재설정할 때 사용된다
- __next__(self)
- 이터러블의 다음 요소를 반환한다. 더 이상 반환할 요소가 없으면 StopIteration 예외를 발생시킨다.
# 리스트는 이터러블입니다.
my_list = [1, 2, 3, 4, 5]
# 리스트에서 이터레이터를 얻을 수 있습니다.
my_iterator = iter(my_list)
# 이터레이터에서 값을 하나씩 꺼낼 수 있습니다.
print(next(my_iterator)) # 출력: 1
print(next(my_iterator)) # 출력: 2
print(next(my_iterator)) # 출력: 3
print(next(my_iterator)) # 출력: 4
print(next(my_iterator)) # 출력: 5
# 더 이상 꺼낼 값이 없으면 StopIteration 예외가 발생합니다.
# print(next(my_iterator)) # 예외 발생: StopIteration
2. 제너레이터 (generator)
이터레이터의 일종으로, 함수 내부에서 ‘yield’ 키워드를 사용해서 값을 하나씩 반환 한다.
2.1 제너레이터 함수
제너레이터 함수는 yield 키워드를 사용하여 값을 반환한다.
함수가 yield를 만나면 현재 상태를 유지하고 호출자에게 값을 반환.
이후 제너레이터가 다시 호출되면, yield 이후의 코드가 실행된다.
def my_range(start, end):
current = start
while current < end:
yield current
current += 1
# 제너레이터 함수 사용
for num in my_range(1, 5):
print(num)
# 출력:
# 1
# 2
# 3
# 4
2.2 제너레이터 표현식
메모리를 절약할 수 있는 제너레이터 객체를 반환한다.
표현식은 소괄호를 사용하여 작성한다.
# 리스트 컴프리헨션
squares_list = [x ** 2 for x in range(10)]
print(squares_list) # 출력: [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
# 제너레이터 표현식
squares_gen = (x ** 2 for x in range(10))
# 제너레이터 표현식 사용
for square in squares_gen:
print(square)
# 출력:
# 0
# 1
# 4
# 9
# 16
# 25
# 36
# 49
# 64
# 81
2.3 제너레이터의 메소드
- __iter__()
- 이터레이터 객체 자체를 반환합니다.
- __next__()
- 제너레이터의 다음 값을 반환합니다.
- send(value)
- 제너레이터의 yield 표현식에 값을 보내고, 다음 yield 표현식을 실행합니다.
- throw(type, value=None, traceback=None)
- 제너레이터 내부에서 예외를 발생시킵니다.
- close()
- 제너레이터를 종료합니다.
def generator_example():
while True:
try:
value = (yield)
print(f"Received: {value}")
except GeneratorExit:
print("Generator closed")
break
except Exception as e:
print(f"Error: {e}")
gen = generator_example()
next(gen) # 제너레이터 초기화
gen.send(10) # 출력: Received: 10
gen.throw(ValueError, "Invalid value") # 출력: Error: Invalid value
gen.close() # 출력: Generator closed
3. 데코레이터
기존 함수나 메서드에 추가적인 기능을 부여하는 기능.
데코레이터는 다른 함수를 인자로 받아 새로운 함수를 반환하는 함수.
주로 코드의 재사용성을 높이고, 함수나 메서드의 동작을 수정하거나 확장하는 데 사용.
3.1 데코레이터 기본 개념
함수를 다른 함수로 감싸서 추가 기능을 제공하는 역할
@를 사용하여 적용 가능
def my_decorator(func):
def wrapper():
print("Something is happening before the function is called.")
func()
print("Something is happening after the function is called.")
return wrapper
@my_decorator
def say_hello():
print("Hello!")
say_hello()
# 출력:
# Something is happening before the function is called.
# Hello!
# Something is happening after the function is called.
3.2 함수 데코레이터
인자로 받는 함수의 동작을 변경하거나 확장하는 함수
def logger(func):
def wrapper(*args, **kwargs):
print(f"Logging: {func.__name__} called with {args}, {kwargs}")
result = func(*args, **kwargs)
print(f"Logging: {func.__name__} returned {result}")
return result
return wrapper
@logger
def add(a, b):
return a + b
print(add(3, 4))
# 출력:
# Logging: add called with (3, 4), {}
# Logging: add returned 7
# 7
3.3 메서드 데코레이터
클래스 메서드에 적용되는 데코레이터
def method_logger(func):
def wrapper(self, *args, **kwargs):
print(f"Logging: {func.__name__} called with {args}, {kwargs}")
result = func(self, *args, **kwargs)
print(f"Logging: {func.__name__} returned {result}")
return result
return wrapper
class MyClass:
@method_logger
def greet(self, name):
return f"Hello, {name}!"
obj = MyClass()
print(obj.greet("Alice"))
# 출력:
# Logging: greet called with ('Alice',), {}
# Logging: greet returned Hello, Alice!
# Hello, Alice!
3.4 데코레이터 체이닝
데코레이터를 하나의 함수에 적용할 수 있다.
def uppercase_decorator(func):
def wrapper(*args, **kwargs):
result = func(*args, **kwargs)
return result.upper()
return wrapper
def logger(func):
def wrapper(*args, **kwargs):
print(f"Logging: {func.__name__} called with {args}, {kwargs}")
result = func(*args, **kwargs)
print(f"Logging: {func.__name__} returned {result}")
return result
return wrapper
@logger
@uppercase_decorator
def say_hello(name):
return f"Hello, {name}"
print(say_hello("Alice"))
# 출력:
# Logging: say_hello called with ('Alice',), {}
# Logging: say_hello returned HELLO, ALICE
# HELLO, ALICE
3.5 인자가 있는 데코레이터
데코레이터를 한 번 더 감사는 함수를 사용하여 인자를 전달할 수 있다.
def repeat(n):
def decorator(func):
def wrapper(*args, **kwargs):
for _ in range(n):
result = func(*args, **kwargs)
return result
return wrapper
return decorator
@repeat(3)
def say_hello():
print("Hello!")
say_hello()
# 출력:
# Hello!
# Hello!
# Hello!
3.6 클래스 데코레이터
클래스 정의를 수정하거나 확장하는 데 사용
def add_repr(cls):
def __repr__(self):
return f"{self.__class__.__name__}({self.__dict__})"
cls.__repr__ = __repr__
return cls
@add_repr
class MyClass:
def __init__(self, x, y):
self.x = x
self.y = y
obj = MyClass(10, 20)
print(obj)
# 출력: MyClass({'x': 10, 'y': 20})
'Language > Python' 카테고리의 다른 글
[Python] 매직 메소드 (0) | 2024.04.28 |
---|---|
[Python] 클래스 (2/2) (0) | 2024.04.28 |
[Python] 클래스 (1/2) (0) | 2024.04.27 |
[Python] 패키지 설치 및 관리 (0) | 2024.04.27 |
[Python] 모듈과 패키지 (0) | 2024.04.27 |