[python] Python 3.6의 변수 주석은 무엇입니까?

Python 3.6이 곧 출시됩니다. PEP 494-Python 3.6 릴리스 일정 에 12 월 말이 언급되어 있으므로 Python 3.6의 새로운 기능 을 살펴보고 변수 주석이 언급되는 것을 확인했습니다 .

PEP 484 는 함수 매개 변수의 유형 주석 (일명 유형 힌트)에 대한 표준을 도입했습니다. 이 PEP는 클래스 변수 및 인스턴스 변수를 포함한 변수 유형에 주석을 달기 위해 Python에 구문을 추가합니다.

primes: List[int] = []

captain: str  # Note: no initial value!

class Starship:
     stats: Dict[str, int] = {}

함수 주석과 마찬가지로 Python 인터프리터는 변수 주석에 특별한 의미를 부여하지 않고 __annotations__클래스 또는 모듈 의 특수 속성에만 저장합니다 . 정적으로 형식화 된 언어의 변수 선언과 달리 주석 구문의 목표는 추상 구문 트리 및 __annotations__속성을 통해 타사 도구 및 라이브러리에 대한 구조화 된 형식 메타 데이터를 쉽게 지정할 수있는 방법을 제공하는 것입니다.

그래서 내가 읽은 내용은 파이썬 3.5의 유형 힌트 란 무엇인가에 설명 된 파이썬 3.5에서 오는 유형 힌트의 일부입니다 .

나는 따라 captain: strclass Starship예를 들어,하지만 반드시 마지막에 대해 : 어떻게 primes: List[int] = []설명? 정수만 허용하는 빈 목록을 정의하고 있습니까?



답변

:와 사이의 모든 것은 =유형 힌트이므로 primes실제로으로 정의 List[int]되고 처음에는 빈 목록으로 설정됩니다 (그리고 stats처음에는로 정의 된 빈 사전입니다 Dict[str, int]).

List[int]Dict[str, int]그러나,이 이미 파이썬 3.5 입력 힌트 PEP에 정의 된 다음 구문의 일부가 아닙니다. 3.6 PEP 526 – 변수 주석에 대한 구문 제안 은 변수 에 동일한 힌트를 첨부하는 구문 정의합니다. 주석 (예 :)이있는 변수에 유형 힌트 만 첨부 할 수 있기 전에 primes = [] # List[int].

모두 List하고 Dict있는 일반 특정 (콘크리트) 내용 목록 또는 사전에 매핑이 있음을 나타냅니다 유형.

의 경우 목록에있는 모든 요소의 유형 인 List‘인수'( [...]구문 의 요소)가 하나뿐입니다 . 의 경우 Dict첫 번째 인수는 키 유형이고 두 번째 인수는 값 유형입니다. 따라서 목록의 모든primes은 정수이고 사전의 모든 키-값 쌍 stats(str, int)쌍이며 문자열을 정수로 매핑합니다.

참고 항목 typing.Listtyping.Dict정의의 섹션 제네릭을 뿐만 아니라, – PEP 483 타입 힌트의 이론 .

함수에 대한 유형 힌트와 마찬가지로 사용은 선택 사항이며 속성을 통해 검사 할 수있는 주석으로 간주됩니다 __annotations__. 이러한 주석에 임의의 정보를 첨부 할 수 있으며 유형 힌트 정보에 엄격하게 제한되지 않습니다.

전체 제안서 를 읽으 실 수 있습니다 . 여기에는 새로운 구문을 넘어서는 몇 가지 추가 기능이 포함되어 있습니다. 예를 들어, 이러한 주석이 평가되는시기,이를 검사하는 방법 및 클래스 속성 대 인스턴스 속성으로 선언하는 방법을 지정합니다.


답변

변수 주석이란 무엇입니까?

변수 주석은 # type에 정의 된대로 주석 의 다음 단계 일뿐 입니다 PEP 484. 이 변경의 근거 는 PEP 526각 섹션에 강조되어 있습니다.

따라서 다음과 같이 유형을 암시하는 대신 :

primes = []  # type: List[int]

형식을 할당하여 유형에 직접 주석을 달 수 있도록 새로운 구문이 도입 되었습니다.

primes: List[int] = []

@Martijn이 지적했듯이에서 사용 가능한 유형을 사용 typing하고 빈 목록으로 초기화 하여 정수 목록을 나타냅니다 .

어떤 변화를 가져 오나요?

도입 된 첫 번째 변경 사항 은 문자 뒤에 독립형으로 이름에 주석을 달거나 선택적으로 주석을 달면서 값을 할당 할 수있는 새로운 구문 입니다 :.

annotated_assignment_stmt ::=  augtarget ":" expression ["=" expression]

따라서 문제의 예 :

   primes: List[int] = [ ]
#    ^        ^         ^
#  augtarget  |         |
#         expression    |
#                  expression (optionally initialize to empty list)

새로운 구문과 함께 추가 변경 사항도 도입되었습니다. 모듈과 클래스는 이제 유형 메타 데이터가 첨부 된 __annotations__속성 ( PEP 3107-Function Annotations 이후의 함수)을 갖습니다 .

from typing import get_type_hints  # grabs __annotations__

이제 __main__.__annotations__선언 된 유형을 보유합니다.

>>> from typing import List, get_type_hints
>>> primes: List[int] = []
>>> captain: str
>>> import __main__
>>> get_type_hints(__main__)
{'primes': typing.List<~T>[int]}

captain모듈에서도 액세스 할 수있는 유형 만 반환 get_type_hints하므로 현재 표시되지 않습니다 get_type_hints. 즉, 먼저 값이 필요합니다.

>>> captain = "Picard"
>>> get_type_hints(__main__)
{'primes': typing.List<~T>[int], 'captain': <class 'str'>}

사용 print(__annotations__)하면 표시 'captain': <class 'str'>되지만 실제로 __annotations__직접 액세스해서는 안됩니다 .

마찬가지로 클래스의 경우 :

>>> get_type_hints(Starship)
ChainMap({'stats': typing.Dict<~KT, ~VT>[str, int]}, {})

a ChainMap는 주어진 클래스 (첫 번째 매핑에 위치)에 대한 주석과 해당 클래스 ( 객체 mro{}대한 결과 매핑) 에서 발견 된 기본 클래스에 정의 된 모든 주석을 가져 오는 데 사용됩니다 .

새로운 구문과 함께 ClassVar클래스 변수를 나타내는 새로운 유형이 추가되었습니다. 그래, stats당신의 예제에서 실제로입니다 인스턴스 변수 A, 없습니다 ClassVar.

강제로 사용해야합니까?

의 유형 힌트와 마찬가지로 PEP 484이들은 완전히 선택 사항 이며 유형 검사 도구 (및이 정보를 기반으로 빌드 할 수있는 다른 모든 도구)에 주로 사용됩니다. Python 3.6의 안정적인 버전이 출시되면 잠정적이므로 향후 약간의 조정이 추가 될 수 있습니다.


답변