python - generator, decorator
제너레이터generator
제너레이터는 파이썬의 시퀀스를 생성하는 객체다. 제너레이터로 전체 시퀀스를 한 번에 메모리에 생성하고 정렬할 필요 없이, 잠재적으로 큰 시퀀스를 순회할 수 있다. 제너레이터는 이터레이터에 대한 데이터의 소스로 자주 사용된다. my_range() 함수는 제너레이터다(일련의 정수를 생성한다).
제너레이터는 실행될 때 함수를 실행하는 것이 아니라, 제너레이터 함수가 가진 객체를 반환한다.
제너레이터는 한번 생성해서 반환한 객체를 보관하지 않기 때문에, 이전의 코드를 실행한 후 추가한 코드를 실행하면 객체가 출력되지 않는다.
제너레이터를 순회할 때마다 마지막으로 호출된 항목을 기억하고 다음 값을 반환한다. 제너레이터는 일반 함수와 다르다. 일반 함수는 이전 호출에 대한 메모리가 없고, 항상 똑같은 상태로 첫 번째 라인부터 수행한다.
잠재적으로 큰 시퀀스를 생성하고, 제너레이터 컴프리헨션에 대한 코드가 아주 긴 경우에는 제너레이터 함수를 사용하면 된다. return 문으로 값을 반환하지 않고, yield 문으로 값을 반환한다.
>>> def my_range(first=0, last=10, step=1):
... number = first
... while number < last:
... yield number
... number += step
다음과 같이 함수를 실행한다
>>> my_range
<function my_range at 0x00000168277BF280>
다음과 같이 제너레이터 객체를 반환한다.
>>> ranger = my_range(1,5)
>>> ranger
<generator object my_range at 0x0000016827800270>
이 제너레이터 객체를 순회할 수 있다.
>>> for x in ranger:
... print(x)
...
2
3
4
데커레이터 decorator
가끔씩 소스 코드를 바꾸지 않고, 사용하고 있는 함수를 수정하고 싶을 때가 있다. 일반적인 예는 함수에 전달된 인자를 보기 위해 디버깅 문을 추가하는 것이다.
데커레이터는 하나의 함수를 취해서 또 다른 함수를 반환하는 함수다. 이 묘책을 사용하기 위해서는 다음과 같은 것들을 사용한다.
- *args와 **kargs
- 내부 함수
- 함수 인자
document_it() 함수는 다음과 같이 데커레이터를 정의한다.
- 함수 이름과 인자값을 출력한다
- 인자로 함수를 실행한다.
- 결과를 출력한다.
- 수정된 함수를 사용할 수 있도록 반환한다.
>>> def document_it(func):
... def new_function(*args, **kargs):
... print('Running function: ', func.__name__)
... print('Positional arguments: ', args)
... print('Keyword argument: ', kwargs)
... result = func(*args, **kargs)
... print('Result: ', result)
... return result
... return new_function
document_it() 함수에 어떤 func 함수 이름을 전달하든지 간에 document_it() 함수에 추가 선언문이 포함된 새 함수를 얻는다. 데커레이터는 실제로 func 함수로부터 코드를 실행하지 않는다. 하지만 document_it() 함수로부터 func를 호출하여 결과뿐만 아니라 새로운 함수를 얻는다.
수동으로 데커레이터를 적용해보자.
>>> def add_ints(a,b):
... return a+b
...
>>> add_ints(3, 5)
8
>>> cooler_add_ints = document_it(add_ints)
>>> cooler_add_ints(3,5)
Running function: add_ints
Positional arguments: (3,5)
Keyword arguments: {}
Result: 8
8
위와 같이 수동으로 데커레이터를 할당하는 대신, 다음과 같이 데커레이터를 사용하고 싶은 함수에 그냥 @데커레이터_이름을 추가한다.
>>> @document_it
... def add_ints(a,b):
... return a+b
...
>>> add_ints(3,5)
Running function: add_ints
Positional arguments: (3,5)
Keyword arguments: {}
Result: 8
8
출처 : Introducing python