[전문가를 위한 파이썬] 5장 일급 함수 내용 정리
일급 객체의 조건
- 런타임에 생성할 수 있다.
- 데이터 구조체의 변수나 요소에 할당할 수 있다.
- 함수 인수로 전달할 수 있다.
- 함수 결과로 반환할 수 있다.
5.1. 함수를 객체처럼 다루기
- __doc__: 객체의 도움말 텍스트 출력
def factorial(n):
"""returns n!"""
return 1 if n < 2 else n * factorial(n-1)
fact = factorial
fact(5) # 120
map(factorial, range(11))
list(map(fact, range(11)))
- 함수를 변수에 할당할 수 있다.
- map()의 인수로도 전달할 수 있다.
- 일급 함수가 있으면 함수형 스타일로 프로그래밍할 수 있다.
5.2. 고위 함수
- 고위함수(high-order function): 함수를 인수로 받거나, 함수를 결과로 반환하는 함수
- 대표적으로 map(), sort(), sorted()가 있음.
5.2.1. map(), filter(), reduce()의 대안
- 함수형 언어는 모두 map(), filter(), reduce() 고위함수를 제공한다.
- 지능형 리스트나 제너레이터 표현식으로 map(), filter() 조합이 처리하는 작업을 표현할 수 있다.
5.3. 익명 함수
- lambda 키워드는 파이썬 표현식 내에 익명함수를 생성한다.
5.4. 일곱 가지 맛의 콜러블 객체
- 호출 연산자인 ()는 사용자 정의 함수 이외의 다른 객체에도 적용할 수 있다.
- 호출할 수 있는 객체인지 알아보려면 callable() 내장 함수를 사용한다.
- 콜러블의 종류
1. 사용자 정의 함수: def 문이나 람다 표현식으로 생성한다.
2. 내장 함수: len()이나 time.strftime() 처럼 C언어로 구현된 함수(CPython의 경우)
3. 내장 메서드: dict.get() 처럼 C언어로 구현된 메서드
4. 메서드: 클래스 본체에 정의된 함수
5. 클래스: 호출될 때 클래스는 자신의 __new__() 메서드를 실행해서 객체를 생성하고, __init__()으로 초기화한 후, 최종적으로 호출자에 객체를 반환한다.
6. 클래스 객체: 클래스가 __call__() 메서드를 구현하려면 이 클래스의 객체는 함수로 호출될 수 있다.
7. 제너레이터 함수: yield 키워드를 사용하는 함수나 메서드. 이 함수가 호출되면 제너레이터 객체를 반환한다.
5.5. 사용자 정의 콜러블형
- 파이썬 함수가 실제 객체일 뿐만 아니라, 모든 파이썬 객체가 함수처럼 동작하게 만들 수 있다. __call__() 인스턴스 메서드를 구현하면 된다.
import random
class BingoCage:
def __init__(self, items):
self._items = list(items)
random.shuffle(self._items)
def pick(self): # 핵심 메서드
try:
return self._items.pop()
except IndexError:
raise LookupError("pick from empty BingoCage")
def __call__(self): # bingo.pick()에 대한 단축 형태로 bingo()를 정의함.
return self.pick()
bingo = BingoCage(range(3))
bingo.pick()
# 1
bingo()
# 0
- BingoCage의 경우 객체를 함수처럼 호출할 때마다 항목을 하나 꺼낸 후 변경된 상태를 유지해야 하는데, __call__() 메서드를 구현하면 이런 객체를 생성하기 쉽다.
- 이러한 예로 데코레이더가 있는데, 데코레이터는 함수이지만 때때로 호출된 후의 상태를 기억할 수 있는 기능이 유용하게 사용된다.
5.6. 함수 인트로스펙션
- __dict__ 속성: 함수는 객체에 할당된 사용자 속성을 __dict__ 속성을 이용해 보관한다.
5.7. 위치 매개변수에서 키워드 전용 매개변수까지
- 함수를 정의할 때 키워드 전용 인수(keyword-only argument)를 지정하려면 *가 붙은 인수 뒤에 이름을 지정한다.
5.8. 매개변수에 대한 정보 읽기
import bobo
@bobo.query("/")
def hello(person):
return "Hello %s!" % person
- bobo.query() 데커레이터는 hello()와 같은 평범한 함수와 프레임워크에서 제공하는 요청처리 메커니즘을 결합시킨다.
- bobo가 hello() 함수의 내부를 조사해서 person이라는 매개변수가 필요하다는 것을 알아내기 때문에, 프로그래머는 요청 객체를 건드릴 필요가 없다.
- 함수 객체 안의 __defaults__ 속성에는 위치(positional) 인수와 키워드 인수의 기본값을 가진 튜플이 들어있다.
def clip(text, max_len=80):
a = 1
b = 2
return a + b
clip.__defaults__ # (80, )
clip.__code__co.varnames # ('text', 'max_len', 'a', 'b')
clip.__code__.co_argcount # 2
5.9. 함수 애너테이션
- 함수 선언에서 각 매개변수에는 : 뒤에 애너테이션 표현식을 추가할 수 있다.
- 애너테이션은 전혀 처리되지 않으며, 단지 함수 객체 안의 dict형 __annotations__속성에 저장될 뿐이다.
5.10. 함수형 프로그래밍을 위한 패키지
5.10.1. operator 모듈
from functools import reduce
from operator import mul
def fact(n):
return reduce(mul, range(1, n+1))
5.10.2. functools.partial() 인수로 고정하기
- functools.partial()은 함수를 부분적으로 실행할 수 있게 해주는 고위함수이다.
from operator import mul
from functools import partial
triple = partial(mul, 3)
triple(7) # 21
5.11. 요약
- 파이썬 함수의 일급 특성의 기본 개념은 함수를 변수에 할당하고, 다른 함수에 전달하고, 데이터 구조체에 저장하며, 함수 속성에 접근해서 프레임워크나 도구가 이 속성 정보를 사용할 수 있게 해주는 것이다.
- 고위함수의 예로 sorted(), min(), max(), functools.partial()이 있다.
- 파이썬에서 콜러블은 람다, __call__() 메서드를 구현하는 클래스 객체 등이 있다. 모든 콜러블은 callable() 내장함수가 탐지할 수 있다.
- functools.partial(), operator 모듈은 함수형 프로그래밍을 할 수 있게 해준다.
딥러닝에서의 일급 함수 예제
https://colab.research.google.com/drive/1paES-cqaKEcAJ29A7aNnqptnBwAm2Qh4#scrollTo=awMOCKXLPoJx