__call__ — 객체를 함수처럼 부르기 ★★
보통 객체는 f(3)처럼 함수 부르듯 부를 수 없어요. 클래스에 __call__이라는 특별한 메서드를 정의하면 그 객체 뒤에 괄호를 붙여 바로 호출할 수 있어요. f(3)이라고 쓰면 파이썬이 내부에서 f.__call__(3)을 실행해요.
| 코드 줄 | 무슨 뜻 |
|---|---|
f = AffineFunction(a=2, b=1) | 객체를 만들고 a = 2, b = 1 저장 |
f(3) | 객체에 괄호를 붙여 부르면 __call__(self=f, x=3) 실행. 2×3 + 1 = 7 |
f(10) | 2×10 + 1 = 21 |
실제 계산은 forward()라는 다른 메서드에 두고, __call__은 그걸 불러 주기만 하게 만들 수도 있어요. 호출 방식은 똑같이 m1(3)인데 안에서는 m1.__call__(3) → forward(3) 순서로 실행돼요. 뒤에서 볼 nn.Module이 정확히 이 방식으로 동작해요.
| 실행하는 줄 | 무슨 뜻 |
|---|---|
print("f(3):", m1(3)) | print가 찍기 전에 괄호 안의 m1(3)부터 계산해야 해요. m1(3) → __call__ → forward 안에서 먼저 "forward() 호출됨"을 찍고 7을 돌려줘요. 그다음 print가 f(3): 7을 찍어요 |
print("f(10):", m1(10)) | 똑같이 "forward() 호출됨"이 먼저, 그다음 f(10): 21 |
그래서 출력 순서가 "forward() 호출됨 → f(3): 7 → forward() 호출됨 → f(10): 21"이에요. 호출 메시지가 결과보다 먼저 나오는 점을 조심하세요. 한편 __call__이 없는 객체를 g(3)처럼 부르면 "이 객체는 호출할 수 없다"는 에러(TypeError)가 나요.
__call__()을 정의한 class의 instance는 f(x)처럼 함수 호출 형태로 사용할 수 있으며, f(x)는 내부적으로 f.__call__(x)를 실행한다. __call__ 안에서 forward()를 실행하면 호출은 f(x)이지만 실제 계산은 forward()에서 이뤄진다. print 안에서 함수를 호출하면 그 함수 속 print가 먼저 찍혀요.
잠깐 확인 — f = AffineFunction(a=3, b=2)에서 f(4)의 값은?
3×4 + 2 = 14예요.
자료: 3~4주차 · Week03_Class_for_PyTorch(pdf, ipynb 업데이트본) · 빅데이터03(3주차)·빅데이터04(4주차) 녹취