람다 함수가 뭐에요? 라는 질문에 답해주다가 문득 생각이 들었어요. def 로 선언한 함수와 lambda로 선언한 익명함수 둘 다 함수 객체지만, 타입 힌트는 def에만 사용할 수 있죠. 그렇다면, 람다 함수를 거쳐 반환값을 변수에 할당한다면 이때 타입 검사는 어떻게 되는가? 가 궁금해졌어요.
pyright를 사용해 타입 검사를 진행했어요. 사용한 코드는 모두 기재해뒀으니, 참고해주세요!
def square_def(x):
return x ** 2
square_lambda = lambda x: x ** 2
a: int = 5
b = square_lambda(a)
c = square_def(a)
def test(b: str) -> None:
print(type(b))
test(b)
test(c)
💡 사용한 코드는 여기 에서 직접 확인할 수 있어요!

위 코드의 경우, test(c)에서만 타입 오류가 발생해요.
square_def의 경우, def로 선언했을 뿐 별도의 타입 힌트를 쓰지 않았으니 실질적으로 타입 정보는 lambda로 선언한 square_lambda와 같을거라 생각했어요. 하지만, square_def의 경우 c의 타입이 int로 정상적으로 추론되었지만 square_lambda의 경우 b의 타입이 추론되지 않았어요. 람다 함수가 타입 정보를 지우는걸까요?
그렇다면, square_lambda라는 람다 함수를 담은 변수 자체에 타입 힌트를 걸어보면 어떨까요?
from typing import Callable
def square_def(x):
return x ** 2
square_lambda: Callable[[int], int] = lambda x: x ** 2
a: int = 5
b = square_lambda(a)
c = square_def(a)
def test(b: str) -> None:
print(type(b))
test(b)
test(c)
💡 사용한 코드는 여기 에서 직접 확인할 수 있어요!
🔎 Callable은 '호출 가능한 객체'에 대한 타입 힌트에요.
Callable[[int], int]의 경우, int형 매개변수 하나를 받아 int형을 반환하는 호출 가능한 객체의 타입 힌트에요.

아까랑 다르게, test(b)에서도 타입 오류가 발생해요. 앞서 타입 정보를 추론하지 못했던 square_lambda에 Callable을 활용해 타입 힌트를 제공하니, b의 타입이 int로 추론되었다는 뜻이에요.
위를 통해, 아래와 같은 결론을 얻었어요.
타입 안전한 파이썬을 위해, 람다 함수를 쓸 때는 Callable 타입 힌트를 함께 사용해보는게 좋을 것 같아요 😄