Callable 객체
호출 연산자인 ()
는 사용자 정의 함수 이외의 다른 객체에도 사용할 수 있다.
호출할 수 있는 객체(Callable)인지 알아보려면 callable()
내장 함수를 사용한다.
파이썬에는 다음과 같은 callable이 있다.
사용자 정의 함수
def 문이나 람다 표현식으로 생성내장 함수
len()
이나time.strftime()
처럼 C언어로 구현된 함수내장 메서드
dict.get()
처럼 C언어로 구현된 메서드메서드
클래스 본체에 정의된 함수클래스
호출될 때 클래스는 자신의__new__()
메서드를 실행해서 객체를 생성하고,__init__()
으로
초기화한 후, 최정적으로 호출자에 객체를 반환한다. 파이썬에서는 new 연산자가 없기 때문에 클래스를 호출하는 것은
함수를 호출하는것과 동일하다.(일반적으로 클래스를 호출하면 해당 클래스의 객체가 생성되지만,__new__()
메서드를
오버라이딩 하면 다르게 작동할 수 있다.)클래스 객체
클래스가__call__()
메서드를 구현하면 이 클래스의 객체는 함수로 호출될 수 있다.제네레이터 함수
yield
키워드를 사용하는 함수나 메서드. 이 함수가 호출되면 제네레이터 객체를 반환한다.
파이썬에는 다양한 callable 형이 존재하기 때문에, callable()
내장 함수를 사용하여 호출할 수 있는 객체인지
판단하는 방법이 가장 안전하다. 아래의 예시를 확인해보자.
>>> abs, str, 13
(<built-in function abs>, <class 'str'>, 13)
>>> [callable(obj) for obj in (abs, str, 13)]
[True, True, False]
abs는 내장 함수, str은 클래스로써 callable형이며, 13은 callable형이 아니다.
이를 확인하기 위해 callable()
내장 함수를 이용하면, 실제로 ["True", "True", "False"]
가 출력됨을 확인할 수 있다.
사용자 정의 callable형
파이썬 함수가 실제 객체일 뿐만 아니라, 모든 파이썬 객체가 함수처럼 동작하게 만들 수 있다.__call__()
인스턴스 메소드를 구현하면 모든 파이썬 객체를 함수처럼 동작하게 만들 수 있다.
import random
class BingoCage:
def __init__(self, items):
self._items = list(items)
# self._items가 리스트이기에 shuffle()메서드 실행 보장
random.shuffle(self._items)
# 핵심 메서드
def pick(self):
try:
return self._items.pop()
except IndexError:
# self._items가 비어있으면 사용자 정의 메시지를 담은 예외 발생시킴
raise LookupError('pick from empty BingoCage')
# bingo.pick()에 대한 단축 형태로 bingo() 정의
def __call__(self):
return self.pick()
>>> bingo = BingoCage(range(3))
>>> bingo.pick()
2
>>> bingo()
0
>>> callable(bingo)
True
BingoCage의 경우 객체를 함수처럼 호출할 때마다 항목을 하나 꺼낸 후 변경된 상태를 유지해야 하는데, __call__()
메서드를 구현하면 이런 객체를 생성하기 쉽다.
이런 예로는 decorator가 있다. decorator는 함수이지만, 때때로 호출된 후의 상태를 기억할 수 있는 기능이 유용하게 사용된다.
reference : Fluent python - 한빛미디어
'CS' 카테고리의 다른 글
[Python] 클로저(Closure)와 내부 함수를 알아보자 (0) | 2022.11.30 |
---|---|
[Python] 함수 인트로스펙션(Function Introspection)과 매개변수(Function Parameter), 애너테이션(Function Annotation) (0) | 2022.11.30 |
[Python] 튜플(Tuple)과 시퀀스의 복합 할당 (0) | 2022.10.23 |
[Python] Python의 내장 시퀀스와 list comp, genexp (0) | 2022.10.23 |
[JavaScript] JavaScript의 객체 (0) | 2022.10.23 |
댓글