[python] 람다 함수에 힌트를 입력 할 수 있습니까?

현재 Python에서 함수의 매개 변수와 반환 유형은 다음과 같이 유형 힌트가 될 수 있습니다.

def func(var1: str, var2: str) -> int:
    return var1.index(var2)

이는 함수가 두 개의 문자열을 취하고 정수를 반환 함을 나타냅니다.

그러나이 구문은 다음과 같은 람다와 매우 혼동됩니다.

func = lambda var1, var2: var1.index(var2)

매개 변수와 반환 유형 모두에 유형 힌트를 입력 해 보았지만 구문 오류를 일으키지 않는 방법을 찾을 수 없습니다.

람다 함수에 힌트를 입력 할 수 있습니까? 그렇지 않은 경우 유형 힌트 람다에 대한 계획이 있습니까? 아니면 이유가 있습니까 (명백한 구문 충돌 외에도) 왜 안됩니까?



답변

일종의 Python 3.6 이상에서 PEP 526 변수 주석을 사용하여 할 수 있습니다 . lambda결과를 할당하는 변수 에 typing.Callablegeneric으로 주석을 달 수 있습니다 .

from typing import Callable

func: Callable[[str, str], int] = lambda var1, var2: var1.index(var2)

이것은 타입 힌팅 정보를 함수 객체 자체에 첨부하는 것이 아니라 객체를 저장 한 네임 스페이스에만 첨부하지만 일반적으로 이것은 타입 힌팅 목적에 필요한 모든 것입니다.

그러나 대신 함수 문을 사용할 수도 있습니다. 에서 lambda제공 하는 유일한 장점 은 더 큰 표현식 안에 간단한 표현식에 대한 함수 정의를 넣을 수 있다는 것 입니다. 그러나 위의 람다는 더 큰 표현식의 일부가 아니며 할당 문의 일부일 뿐이며 이름에 바인딩합니다. 이것이 바로 def func(var1: str, var2: str): return var1.index(var2)성명서가 달성 할 수있는 것입니다.

상태에 대한 문서로 주석 *args이나 **kwargs인수를 별도로 지정할 수 없습니다 Callable.

선택적 또는 키워드 인수를 나타내는 구문은 없습니다. 이러한 함수 유형은 콜백 유형으로 거의 사용되지 않습니다.

그 제한은 적용되지 않습니다 PEP 544 프로토콜 A의 __call__방법 ; 어떤 인수를 받아 들여야하는지에 대한 표현적인 정의가 필요한 경우이를 사용하십시오. Python 3.8이 필요 하거나 백 포트 용 typing-extensions프로젝트 를 설치해야합니다 .

from typing-extensions import Protocol

class SomeCallableConvention(Protocol):
    def __call__(var1: str, var2: str, spam: str = "ham") -> int:
        ...

func: SomeCallableConvention = lambda var1, var2, spam="ham": var1.index(var2) * spam

를 들어 lambda표현 자체 , 당신은 어떤 주석 (파이썬의 유형 힌트가 구축되는 구문)를 사용할 수 없습니다. 구문은 def함수 문 에만 사용할 수 있습니다 .

에서 – PEP 3107 기능 주석 :

lambda의 구문은 주석을 지원하지 않습니다. 람다 구문은 매개 변수 목록을 괄호로 묶어 주석을 지원하도록 변경할 수 있습니다. 그러나 다음과 같은 이유로 변경하지 않기로 결정했습니다 .

  • 호환되지 않는 변경입니다.
  • 어쨌든 Lambda는 중성화됩니다.
  • 람다는 항상 함수로 변경할 수 있습니다.

여전히 주석을 객체에 직접 첨부 할 수 있으며 function.__annotations__속성은 쓰기 가능한 사전입니다.

>>> def func(var1: str, var2: str) -> int:
...     return var1.index(var2)
...
>>> func.__annotations__
{'var1': <class 'str'>, 'return': <class 'int'>, 'var2': <class 'str'>}
>>> lfunc = lambda var1, var2: var1.index(var2)
>>> lfunc.__annotations__
{}
>>> lfunc.__annotations__['var1'] = str
>>> lfunc.__annotations__['var2'] = str
>>> lfunc.__annotations__['return'] = int
>>> lfunc.__annotations__
{'var1': <class 'str'>, 'return': <class 'int'>, 'var2': <class 'str'>}

Not that dynamic annotations like these are going to help you when you wanted to run a static analyser over your type hints, of course.


답변

Since Python 3.6, you can (see PEP 526):

from typing import Callable
is_even: Callable[[int], bool] = lambda x: (x % 2 == 0)


답변

No, it is not possible, there are no plans to change this, and the reasons are primarily syntactical.


답변