파이썬 3.5에서 가장 많이 언급 된 기능 중 하나는 타입 힌트 입니다.
의 예 타입 힌트 에서 언급 이 문서 와 이것 또한 책임 타입 힌트를 사용하는 언급하면서. 누군가가 그들에 대해 그리고 언제 사용해야하는지, 그렇지 않을 때에 대해 더 설명 할 수 있습니까?
파이썬 3.5에서 가장 많이 언급 된 기능 중 하나는 타입 힌트 입니다.
의 예 타입 힌트 에서 언급 이 문서 와 이것 또한 책임 타입 힌트를 사용하는 언급하면서. 누군가가 그들에 대해 그리고 언제 사용해야하는지, 그렇지 않을 때에 대해 더 설명 할 수 있습니까?
답변:
내가 읽고 제안 PEP (483) 및 PEP 484을 시청 이 타입 힌팅에 귀도하여 프리젠 테이션을.
간단히 말해서 : 유형 힌트는 말 그대로 단어의 의미 입니다. 사용중인 객체의 유형을 암시합니다 .
파이썬 의 동적 인 특성 으로 인해 사용중인 객체 의 유형 을 유추하거나 확인하는 것이 특히 어렵습니다. 이 사실은 개발자가 작성하지 않은 코드에서 정확히 무슨 일이 일어나고 있는지, 그리고 무엇보다도 많은 IDE (PyCharm, PyDev가 떠오름)에서 발견되는 형식 검사 도구에 대해 정확히 이해하기 어렵습니다. 객체의 유형에 대한 표시기가 없습니다. 결과적으로 그들은 프레젠테이션에서 언급 한 것처럼 약 50 %의 성공률로 유형을 추론하려고 시도합니다.
Type Hinting 프레젠테이션에서 두 가지 중요한 슬라이드를 가져 오려면
TypeErrors
입니다..
객체에 대해 정의되지 않은 메소드 / 속성 팝업이 나타납니다.이 작은 소개에 대한 마지막 참고 사항 : 이것은 선택적 기능이며, 내가 이해 한 바에 따르면 정적 입력의 이점을 얻기 위해 소개되었습니다.
일반적으로 걱정할 필요 가 없으며 확실히 사용할 필요가 없습니다 (특히 Python을 보조 스크립팅 언어로 사용하는 경우). 견고성, 제어력 및 추가 디버깅 기능을 많이 제공하므로 대규모 프로젝트를 개발할 때 도움이됩니다 .
이 답변을보다 완벽하게하기 위해 약간의 데모가 적합하다고 생각합니다. mypy
Type Hints가 PEP에 제시 될 때 영감을 얻은 라이브러리 인을 사용할 것 입니다. 이것은 주로이 질문에 부딪 히고 어디서부터 시작 해야할지 궁금한 사람을 위해 작성되었습니다.
그렇게하기 전에 다음을 반복 할 수 있습니다. PEP 484 는 아무 것도 시행하지 않습니다. 단순히 함수 주석의 방향을 설정하고 유형 검사 수행 방법에 대한 지침을 제안 합니다. 함수에 주석을 달고 원하는만큼 힌트를 줄 수 있습니다. 파이썬 자체는 주석을 사용하지 않기 때문에 주석의 존재 여부에 관계없이 스크립트는 계속 실행됩니다.
어쨌든 PEP에 명시된 바와 같이 힌트 유형은 일반적으로 세 가지 형식을 취해야합니다.
# type: type
처음 두 양식을 보완하는 특별 의견. (참고 : Python 3.6 업데이트 주석은 Python 3.6의 변수 주석은 무엇입니까?# type: type
)또한에 typing
도입 된 새로운 모듈 과 함께 유형 힌트를 사용하려고합니다 Py3.5
. 여기에는 정적 검사에 사용하기 위해 도우미 기능 및 데코레이터와 함께 많은 (추가) ABC (Abstract Base Classes)가 정의됩니다. 대부분 ABCs
에 collections.abc
포함되어 있지만에서 Generic
순서 형태 (A 정의하여 가입을 허용하는 __getitem__()
방법).
이것에 대한 더 자세한 설명에 관심이있는 사람 mypy documentation
은 매우 훌륭하게 작성되었으며 검사기의 기능을 설명 / 설명하는 많은 코드 샘플이 있습니다. 확실히 읽을 가치가 있습니다.
첫째, 특별한 의견을 사용할 때 얻을 수있는 행동 중 일부를 관찰하는 것이 흥미 롭습니다. 특별한# type: type
변수를 할당하는 동안 개체를 직접 추론 할 수없는 경우 개체 유형을 나타 내기 위해 메모를 추가 할 수 있습니다. 간단한 과제는 일반적으로 쉽게 추론되지만 목록과 같은 내용 (내용과 관련하여)은 할 수 없습니다.
참고 : 우리의 파생 제품을 사용하려는 경우 Containers
우리는 그 컨테이너의 내용을 지정해야 합니다 사용 일반적인 으로부터 유형을 typing
모듈. 이들은 인덱싱을 지원합니다.
# generic List, supports indexing.
from typing import List
# In this case, the type is easily inferred as type: int.
i = 0
# Even though the type can be inferred as of type list
# there is no way to know the contents of this list.
# By using type: List[str] we indicate we want to use a list of strings.
a = [] # type: List[str]
# Appending an int to our list
# is statically not correct.
a.append(i)
# Appending a string is fine.
a.append("i")
print(a) # [0, 'i']
이러한 명령을 파일에 추가하고 인터프리터로 실행하면 모든 것이 제대로 작동하고 print(a)
list의 내용을 인쇄합니다 a
. # type
의견은 폐기 된 추가 의미 론적 의미가없는 일반 주석으로 취급 .
mypy
반면에 이것을 사용 하여 다음과 같은 응답을 얻습니다.
(Python3)jimmi@jim: mypy typeHintsCode.py
typesInline.py:14: error: Argument 1 to "append" of "list" has incompatible type "int"; expected "str"
str
객체 목록에 int
정적으로 말하는 소리를 포함 할 수 없음을 나타 냅니다. 이는 객체 의 유형을 a
추가하고 추가하는 것만으로 str
또는 내용의 유형을 변경하여 a
값이 허용됨을 나타내도록 수정할 수 있습니다 ( 에서 가져온 List[Any]
후 직관적으로 수행됨 ).Any
typing
함수 어노테이션은 param_name : type
함수 시그니처의 각 매개 변수 뒤에 양식에 추가되며 리턴 함수 유형은 -> type
종료 함수 콜론 앞의 표기법을 사용하여 지정됩니다 . 모든 주석은 __annotations__
편리한 사전 양식으로 해당 기능 의 속성에 저장됩니다 . 간단한 예제 사용 ( typing
모듈 에서 추가 유형이 필요하지 않음 ) :
def annotated(x: int, y: str) -> bool:
return x < y
annotated.__annotations__
속성은 이제 다음과 같은 값을가집니다 :
{'y': <class 'str'>, 'return': <class 'bool'>, 'x': <class 'int'>}
우리가 완전한 noobie이거나 Py2.7
개념 에 익숙하고 결과적으로 TypeError
비교에 숨어있는 것을 알지 못하면 annotated
다른 정적 검사를 수행하고 오류를 포착하여 문제를 해결할 수 있습니다.
(Python3)jimmi@jim: mypy typeHintsCode.py
typeFunction.py: note: In function "annotated":
typeFunction.py:2: error: Unsupported operand types for > ("str" and "int")
무엇보다도 잘못된 인수로 함수를 호출하면 다음과 같은 결과가 나타납니다.
annotated(20, 20)
# mypy complains:
typeHintsCode.py:4: error: Argument 2 to "annotated" has incompatible type "int"; expected "str"
이것들은 기본적으로 모든 유스 케이스로 확장 될 수 있으며 잡힌 오류는 기본 호출 및 작업보다 더 확장됩니다. 확인할 수있는 유형은 실제로 유연하며 잠재력의 작은 몰래 피크를 제공했습니다. typing
모듈, PEP 또는 mypy
문서를 살펴보면 제공되는 기능에 대한보다 포괄적 인 아이디어를 얻을 수 있습니다.
스텁 파일은 서로 다른 두 가지 비 독점적 인 경우에 사용할 수 있습니다.
스텁 파일 (확장자 .pyi
)은 사용하거나 사용하려는 모듈의 주석이 달린 인터페이스입니다. 여기에는 버린 함수 본문으로 유형을 검사하려는 함수의 서명이 포함됩니다. 다음과 같은 이름의 모듈에 세 개의 임의 함수 세트가 제공됩니다 randfunc.py
.
def message(s):
print(s)
def alterContents(myIterable):
return [i for i in myIterable if i % 2 == 0]
def combine(messageFunc, itFunc):
messageFunc("Printing the Iterable")
a = alterContents(range(1, 20))
return set(a)
스텁 파일을 만들 수 있으며 randfunc.pyi
, 원하는 경우 제한을 둘 수 있습니다. 단점은 스텁없이 소스를 보는 사람이 실제로 전달되어야하는 것을 이해하려고 할 때 주석 지원을 실제로 얻지 못한다는 것입니다.
어쨌든, 스텁 파일의 구조는 매우 간단합니다. 모든 함수 정의를 빈 바디 ( pass
채워진)로 추가하고 요구 사항에 따라 주석을 제공하십시오. 여기서는 int
컨테이너의 유형으로 만 작업하고 싶다고 가정 해 봅시다 .
# Stub for randfucn.py
from typing import Iterable, List, Set, Callable
def message(s: str) -> None: pass
def alterContents(myIterable: Iterable[int])-> List[int]: pass
def combine(
messageFunc: Callable[[str], Any],
itFunc: Callable[[Iterable[int]], List[int]]
)-> Set[int]: pass
이 combine
함수는 왜 다른 파일에서 주석을 사용하고 싶을지를 나타내며, 때로는 코드를 어지럽히고 가독성을 떨어 뜨립니다 (파이썬의 경우 큰 아니오). 물론 별칭을 사용할 수도 있지만 때로는 도움이되는 것보다 더 혼란 스럽습니다 (현명하게 사용하십시오).
이를 통해 파이썬에서 타입 힌트의 기본 개념을 익힐 수 있습니다. 사용 된 유형 검사기이지만
mypy
점차적으로 더 많은 팝업을보아야합니다. 일부 내부에서는 IDE ( PyCharm ) 및 다른 일부는 표준 파이썬 모듈로 표시됩니다. 다음 목록에 추가 체커 / 관련 패키지를 추가하고 추가 할 때 (또는 제안 된 경우) 추가하려고합니다.
내가 아는 체커 :
관련 패키지 / 프로젝트 :
이 typeshed
프로젝트는 실제로 자신의 프로젝트에서 유형 힌트를 사용하는 방법을 볼 수있는 가장 좋은 장소 중 하나입니다. 해당 파일 에서 클래스 의 __init__
던전을Counter
예로 들어 보겠습니다 .pyi
.
class Counter(Dict[_T, int], Generic[_T]):
@overload
def __init__(self) -> None: ...
@overload
def __init__(self, Mapping: Mapping[_T, int]) -> None: ...
@overload
def __init__(self, iterable: Iterable[_T]) -> None: ...
어디 _T = TypeVar('_T')
일반적인 클래스를 정의하는 데 사용됩니다 . 를 들어 Counter
클래스 우리는 하나, 그것의 초기화에 인수를 취하지 하나 얻을 수 있음을 알 수 Mapping
에 모든 종류의를 int
또는 가지고 Iterable
모든 종류의를.
주의 : 내가 언급 한 것을 잊어 버린 한 가지는 typing
모듈이 잠정적으로 도입되었다는 것 입니다. 에서 PEP 411 :
임시 패키지는 "안정된"상태로 "졸업"하기 전에 API를 수정했을 수 있습니다. 한편으로,이 상태는 공식적으로 Python 배포판의 일부가되는 이점을 패키지에 제공합니다. 반면에 핵심 개발 팀은 패키지 API의 안정성과 관련하여 약속이 없으며 다음 릴리스에서 변경 될 수 있다고 명시 적으로 밝혔습니다. 예상치 못한 결과로 간주되지만 API 또는 유지 관리에 대한 우려가 입증 된 경우 이러한 패키지는 사용 중단 기간없이 표준 라이브러리에서 제거 될 수도 있습니다.
소금을 꼬집어 여기로 가져 가십시오. 나는 그것이 중요한 방법으로 제거되거나 변경 될 것이라고 의심하지만 아무도 알 수 없습니다.
** 타입 힌트의 범위에서 또 다른 전체 주제 만 유효합니다 : PEP 526
: 구문 변수 주석을 대체하기위한 노력의 일환이다 # type
사용자가 간단한 변수의 유형을 주석 할 수 있습니다 새로운 구문을 도입하여 의견을 varname: type
진술.
Python 3.6의 변수 주석이란 무엇입니까?를 참조하십시오 . 앞에서 언급했듯이 이것에 대한 작은 소개가 필요합니다.
Jim의 정교한 답변에 추가 :
typing
모듈 점검 –이 모듈은 PEP 484에 지정된 유형 힌트를 지원합니다 .
예를 들어 아래 함수는 type 값을 가져 와서 반환 str
하며 다음과 같이 주석이 달립니다.
def greeting(name: str) -> str:
return 'Hello ' + name
이 typing
모듈은 또한 다음을 지원합니다.
새로 출시 된 PyCharm 5는 유형 힌트를 지원합니다. 블로그 게시물 ( PyCharm 5의 Python 3.5 유형 힌트 참조 ) 에서 유형 힌트가 무엇인지 아닌지에 대한 훌륭한 설명을 제공합니다 코드에서이를 사용하는 방법에 대한 몇 가지 예제 및 삽화와 함께 제공 .
또한 이 주석 에서 설명하는 것처럼 Python 2.7에서 지원됩니다 .
PyCharm은 Python 2.7, Python 3.2-3.4 용 PyPI의 타이핑 모듈을 지원합니다. 2.7의 경우 함수 주석이 Python 3.0에서 추가되었으므로 * .pyi 스텁 파일에 유형 힌트를 입력해야합니다 .
유형 힌트는 최근 수십 년 동안 헝가리어처럼 단순한 이름 지정 규칙을 사용하지 않는 동적 언어에 최근 추가되었습니다 (첫 글자 b = 부울 리언, c = 문자, d = 사전, i = 정수, l = 목록, n = 숫자 인 객체 레이블 , s = string, t = tuple)은 너무 번거롭지 않았지만 이제는 오 기다려 ... 언어 (type ())을 사용하여 객체를 인식하고 멋진 IDE를 사용하는 것은 너무 많은 문제라고 결정했습니다. 복잡하고 역동적으로 할당 된 객체 값은 어쨌든 완전히 쓸모 없게 만드는 반면, 간단한 이름 지정 규칙은 모든 개발자를 위해 모든 것을 간단하게 해결할 수 있습니다.
타입 힌트는 유지 관리를위한 것이며 파이썬에 의해 해석되지 않습니다. 아래 코드에서 줄 def add(self, ic:int)
은 다음 return...
줄 까지 오류가 발생하지 않습니다 .
class C1:
def __init__(self):
self.idn = 1
def add(self, ic: int):
return self.idn + ic
c1 = C1()
c1.add(2)
c1.add(c1)
Traceback (most recent call last):
File "<input>", line 1, in <module>
File "<input>", line 5, in add
TypeError: unsupported operand type(s) for +: 'int' and 'C1'