Python 3.0에 도입된 함수 주석에는 함수 매개변수 및 반환 값에 임의의 메타데이터를 추가할 수 있는 기능이 추가되었습니다. 파이썬 3부터 함수 주석이 공식적으로 파이썬에 추가되었습니다(PEP-3107). 주요 목적은 메타데이터를 함수 매개변수 및 반환 값에 연결하는 표준 방법을 갖는 것이었습니다.
함수 주석의 기본
함수 주석의 몇 가지 기본 사항을 이해합시다 -
-
함수 주석은 매개변수와 반환 값 모두에 대해 완전히 선택 사항입니다.
-
함수 주석은 컴파일 시간에 함수의 다양한 부분을 임의의 파이썬 표현식과 연결하는 방법을 제공합니다.
-
PEP-3107은 기본 제공 유형에 대해서도 어떤 종류의 표준 의미론도 도입하지 않습니다. 이 모든 작업은 타사 라이브러리에 맡겨졌습니다.
구문
단순 매개변수 주석
매개변수에 대한 주석은 다음 형식을 취합니다. -
def foo(x: expression, y: expression = 20): ….
초과 매개변수에 대한 주석은 다음과 같습니다. -
def foo(**args: expression, **kwargs: expression): …..
중첩 매개변수의 경우 주석은 항상 매개변수의 이름을 따르고 마지막 괄호까지는 표시되지 않습니다. 중첩 매개변수의 모든 매개변수에 주석을 달 필요는 없습니다.
def foo(x1, y1: expression), (x2: expression, y2: expression)=(None, None)): ……
파이썬은 주석과 함께 의미 체계를 제공하지 않는다는 것을 이해하는 것이 중요합니다. 메타데이터를 연결하고 쉽게 액세스할 수 있는 좋은 구문 지원만 제공합니다. 또한 주석은 필수가 아닙니다.
>>> def func(x:'annotating x', y: 'annotating y', z: int) -> float: print(x + y + z)
위의 예에서 함수 func()는 x,y 및 z라는 세 개의 매개 변수를 사용하여 최종적으로 합을 인쇄합니다. 첫 번째 인수 x는 '주석 x' 문자열로 주석 처리되고, 두 번째 인수 y는 'y 주석 달기' 문자열로 주석 처리되며, 세 번째 인수 z는 int 유형으로 주석 처리됩니다. 반환 값은 float 유형으로 주석 처리됩니다. 다음은 반환 값에 주석을 추가하는 '->' 구문입니다.
출력
>>> func(2,3,-4) 1 >>> func('Function','-','Annotation') Function-Annotation
위에서 func()를 두 번 호출합니다. 한 번은 int 인수로, 한 번은 문자열 인수로 호출합니다. 두 경우 모두 func()가 올바른 작업을 수행하고 주석은 단순히 무시됩니다. 따라서 우리는 주석이 func() 함수의 실행에 영향을 미치지 않는다는 것을 알 수 있습니다.
함수 주석 액세스
모든 주석은 __annotations__라는 사전에 저장되며, 그 자체가 함수 −
의 속성입니다.>>> def func(x:'annotating x', y: 'annotating y', z: int) -> float: print(x + y + z) >>> func.__annotations__ {'x': 'annotating x', 'y': 'annotating y', 'z': <class 'int'>, 'return': <class 'float'>}
앞의 코드 예제에서 볼 수 있듯이 주석은 유형이 지정된 선언이 아니지만 해당 용도로 확실히 사용할 수 있으며 아래에 표시된 것처럼 일부 다른 언어에서 사용되는 입력 구문과 유사합니다. −
>>> def func(a: 'python', b: {'category: ' 'language'}) -> 'yep': pass >>> func.__annotations__ {'a': 'python', 'b': {'category: language'}, 'return': 'yep'} >>>
이는 임의의 값을 __annotations__ 사전에 저장할 수 있음을 의미하는 임의의 표현식입니다. 값을 저장해야 한다는 점을 제외하고는 파이썬 자체에 많은 의미를 추가하지 않습니다. 즉, 매개변수와 반환 유형을 정의하는 것은 함수 주석의 일반적인 사용입니다.
@no_type_check 데코레이터
주석이 유형 선언이라고 가정하는 도구를 사용하고 있지만 다른 목적으로 주석을 사용하려는 경우 여기에 표시된 것처럼 표준 @no_type_check 데코레이터를 사용하여 이러한 처리에서 함수를 면제하십시오. −
>>> from typing import no_type_check >>> @no_type_check def func(a: 'python', b: {'category: ' 'language'}) -> 'yep': pass >>>
일반적으로 주석을 사용하는 대부분의 도구에는 주석을 의미하는 것을 인식하는 방법이 있으므로 이것은 필요하지 않습니다. 데코레이터는 사물이 모호한 모서리 케이스를 보호하기 위한 것입니다.
함수 데코레이터에 대한 입력으로 주석
주석 값은 데코레이터에 대한 입력을 제공하는 좋은 방법이고 데코레이터 생성 래퍼는 주석에 의미를 부여하는 코드를 배치하기에 좋은 장소이기 때문에 주석은 데코레이터와 잘 결합됩니다.
from functools import wraps def adapted(func): @wraps(func) def wrapper(**kwargs): final_args = {} for name, value in kwargs. items(): adapt = func.__annotations__.get(name) if adapt is not None: final_args[name] = adapt(value) else: final_args[name] = value result = func(**final_args) adapt = func.__annotations__.get('result') if adapt is not None: return adapt(result) return result return wrapper @adapted def func(a: int, b: repr) -> str: return a
따라서 적응된 데코레이터는 함수를 래퍼로 묶습니다. 이 래퍼는 키워드 인수만 허용합니다. 즉, 원래 함수가 위치 인수를 허용하더라도 이름으로 지정해야 함을 의미합니다.
함수가 래핑되면 래퍼는 함수의 매개변수 주석에서 어댑터를 찾아 실제 함수에 인수를 전달하기 전에 적용합니다.
함수가 반환되면 래퍼는 반환 값 어댑터를 확인합니다. 하나를 찾으면 최종적으로 반환하기 전에 반환 값에 적용합니다.
우리가 여기서 일어나는 일의 의미를 고려할 때, 그것들은 꽤 인상적입니다. 함수에 매개변수를 전달하거나 값을 반환한다는 의미를 실제로 수정했습니다.
키워드 인수
때로는 메서드의 매개변수 중 하나 이상이 self의 속성에 할당하는 것을 제외하고는 처리가 필요하지 않습니다. 데코레이터와 주석을 사용하여 이를 자동으로 수행할 수 있습니까? 물론 할 수 있습니다.
from functools import wraps def store_args(func): @wraps(func) def wrapper(self, **kwargs): for name, value in kwargs.items(): attrib = func.__annotations__.get(name) if attrib is True: attrib = name if isinstance(attrib, str): setattr(self, attrib, value) return func(self, **kwargs) return wrapper class A: @store_args def __init__(self, first: True, second: 'example'): pass a = A(first = 5, second = 6) assert a.first == 5 assert a.example == 6