`TypeVar` 설명

8405 단어 typespythontyping
Python의 유형 주석에 완전히 익숙하지 않은 경우 my가 시작해야 합니다.

이번 포스트에서는 타입 변수, 즉 TypeVar 를 재미있고 유익하게 사용하는 방법을 알려드리려고 합니다.

문제



이 함수는 무엇이든 인수로 받아들이고 그대로 반환합니다. 반환 유형이 arg 의 유형과 같다는 것을 유형 검사기에 어떻게 설명합니까?

def identity(arg):
    return arg


Any 를 사용하지 않는 이유는 무엇입니까?




def identity(arg: Any) -> Any:
    return arg

Any 를 사용하면 유형 검사기가 이 함수의 작동 방식을 이해하지 못할 것입니다. 관련되는 한 함수는 무엇이든 반환할 수 있습니다. 반환 유형은 arg 의 유형에 의존하지 않습니다.

여기서는 numberint가 되기를 원하므로 유형 검사기가 다음 줄에서 오류를 포착합니다.

다른 유형에 대해 기능을 전문화하지 않는 이유는 무엇입니까?



def identity_int(arg: int) -> int:
    return arg

def identity_int(arg: str) -> str:
    return arg

def identity_list_str(arg: list[str]) -> list[str]:
    return arg

...

  • 확장성이 좋지 않습니다. 동일한 기능을 10번 복제할 예정입니까? 동기화를 유지하는 것을 기억하시겠습니까?
  • 이것이 라이브러리 기능이면 어떻게 됩니까? 사람들이 이 기능을 사용할 모든 방식을 예측할 수는 없습니다.

  • 해결책: 유형 변수



    유형 변수를 사용하면 여러 유형을 함께 연결할 수 있습니다. 다음은 유형 변수를 사용하여 identity 함수에 주석을 추가하는 방법입니다.

    from typing import TypeVar
    
    T = TypeVar("T")
    
    def identity(arg: T) -> T:
        return arg
    


    여기서 반환 유형은 매개변수 유형에 "연결"되어 있습니다. 함수에 무엇을 입력하든 동일한 결과가 나타납니다.

    이것이 실제로 작동하는 모습입니다(Pylance가 있는 VSCode에서).



    유형 변수에 제약 조건 넣기



    잘 입력된 함수입니까?

    def triple(string: Union[str, bytes]) -> Union[str, bytes]:
        return string * 3
    


    그렇지 않습니다. 문자열을 전달하면 바이트와 마찬가지로 항상 문자열을 얻습니다. 이것은 str를 얻을 때와 bytes를 다시 얻을 때를 알기 때문에 약간의 고통을 줄 것입니다.


    "str를 전달하면 str를 얻습니다. bytes를 전달하면 bytes를 얻습니다."-- 유형 변수에 대한 작업처럼 들립니다.



    충분히 공평합니다. 모든 유형이 곱셈을 지원하는 것은 아닙니다. 유형 변수가 str 또는 bytes(및 해당 하위 클래스)만 허용하도록 제한할 수 있습니다.

    AnyString = TypeVar("AnyString", str, bytes)
    
    def triple(string: AnyString) -> AnyString:
        return string * 3
    
    unicode_scream = triple("A") + "!"
    bytes_scream = triple(b"A") + b"!"
    


    유형 변수를 매개변수로 사용


    list 또는 Iterable 와 같은 일반 유형에 대한 매개변수로 유형 변수를 사용할 수도 있습니다.

    def remove_falsey_from_list(items: list[T]) -> list[T]:
        return [item for item in items if item]
    
    def remove_falsey(items: Iterable[T]) -> Iterator[T]:
        for item in items:
            if item:
                yield item
    


    그러나 이것은 꽤 빨리 까다로워집니다. 다음 글에서 자세히 다루겠습니다.

    연결


  • mypy 일반 함수에 대한 설명서: https://mypy.readthedocs.io/en/stable/generics.html#generic-functions
  • 좋은 웹페이지 즐겨찾기