programing

Python3의 "함수 주석"의 좋은 용도는 무엇입니까?

goodsources 2023. 5. 11. 21:25
반응형

Python3의 "함수 주석"의 좋은 용도는 무엇입니까?

기능 주석: PEP-3107

Python3의 함수 주석을 보여주는 코드 조각을 우연히 발견했습니다.개념은 간단하지만 왜 이것들이 Python3에서 구현되었는지 또는 그것들에 대한 좋은 용도가 있는지 생각이 나지 않습니다.아마도 SO가 저를 깨우쳐줄 수 있을까요?

작동 방식:

def foo(a: 'x', b: 5 + 6, c: list) -> max(2, 9):
    ... function body ...

에 오는 것은 '이고, 다음에 는 '주석'입니다.->함수의 반환 값에 대한 주석입니다.

foo.func_communications는 사전을 반환합니다.

{'a': 'x',
 'b': 11,
 'c': list,
 'return': 9}

이것을 이용할 수 있다는 것이 무슨 의미가 있습니까?

함수 주석은 사용자가 작성하는 것입니다.

문서화에 사용할 수 있습니다.

def kinetic_energy(mass: 'in kilograms', velocity: 'in meters per second'):
     ...

사전 조건 확인에 사용할 수 있습니다.

def validate(func, locals):
    for var, test in func.__annotations__.items():
        value = locals[var]
        msg = 'Var: {0}\tValue: {1}\tTest: {2.__name__}'.format(var, value, test)
        assert test(value), msg


def is_int(x):
    return isinstance(x, int)

def between(lo, hi):
    def _between(x):
            return lo <= x <= hi
    return _between

def f(x: between(3, 10), y: is_int):
    validate(f, locals())
    print(x, y)


>>> f(0, 31.1)
Traceback (most recent call last):
   ... 
AssertionError: Var: y  Value: 31.1 Test: is_int

또한 유형 검사를 구현하는 방법은 http://www.python.org/dev/peps/pep-0362/ 을 참조하십시오.

저는 이것이 실제로 훌륭하다고 생각합니다.

학술적 배경에서 나온 주석은 자바와 같은 언어를 위한 스마트 정적 분석기를 가능하게 하는 데 매우 귀중한 것으로 입증되었다고 말할 수 있습니다.예를 들어, 상태 제한, 액세스가 허용되는 스레드, 아키텍처 제한 등과 같은 의미론을 정의할 수 있으며, 컴파일러에서 얻을 수 있는 것 이상의 확신을 제공하기 위해 이러한 의미론을 읽고 처리할 수 있는 도구가 꽤 있습니다.당신은 심지어 전제 조건/사후 조건을 확인하는 것들을 쓸 수 있습니다.

파이썬은 타이핑이 약하기 때문에 이와 같은 것이 특히 필요하다고 생각하지만, 이것을 공식 구문의 일부로 단순하게 만드는 구조는 실제로 없었습니다.

주석에는 확신할 수 없는 다른 용도가 있습니다.저는 어떻게 제 자바 기반 도구를 파이썬에 적용할 수 있는지 알 수 있습니다.예를 들어, 저는 메서드에 특별한 경고를 할당하고, 메서드를 호출할 때 해당 문서를 읽어야 한다는 표시를 제공하는 도구를 가지고 있습니다(예: 음수 값으로 호출해서는 안 되는 메서드가 있지만 이름에서 직관적이지는 않습니다).주석을 달면 기술적으로 파이썬을 위해 이런 것을 쓸 수 있습니다.마찬가지로, 공식 구문이 있는 경우 태그를 기반으로 대규모 클래스의 메서드를 구성하는 도구를 작성할 수 있습니다.

이것은 상당히 늦은 답변이지만, AFAICT, 함수 주석을 가장 잘 사용하는 것은 PEP-0484 MyPy입니다.또한 VSCode에서 사용되며 CLI를 통해 사용할 수 있는 Microsoft의 PyRight도 있습니다.

Mypy는 Python용 선택적 정적 유형 검사기입니다.Python 3.5 베타 1(PEP 484)에 도입된 형식 주석에 대한 다가오는 표준을 사용하여 Python 프로그램에 형식 힌트를 추가하고 mypy를 사용하여 정적으로 형식 확인을 할 수 있습니다.

다음과 같이 사용:

from typing import Iterator

def fib(n: int) -> Iterator[int]:
    a, b = 0, 1
    while a < n:
        yield a
        a, b = b, a + b

여기에 제 대답에서 좋은 사용의 구체적인 예를 추가하기 위해 장식가와 결합하여 다중 방법을 위한 간단한 메커니즘을 수행할 수 있습니다.

# This is in the 'mm' module

registry = {}
import inspect

class MultiMethod(object):
    def __init__(self, name):
        self.name = name
        self.typemap = {}
    def __call__(self, *args):
        types = tuple(arg.__class__ for arg in args) # a generator expression!
        function = self.typemap.get(types)
        if function is None:
            raise TypeError("no match")
        return function(*args)
    def register(self, types, function):
        if types in self.typemap:
            raise TypeError("duplicate registration")
        self.typemap[types] = function

def multimethod(function):
    name = function.__name__
    mm = registry.get(name)
    if mm is None:
        mm = registry[name] = MultiMethod(name)
    spec = inspect.getfullargspec(function)
    types = tuple(spec.annotations[x] for x in spec.args)
    mm.register(types, function)
    return mm

및 사용 예:

from mm import multimethod

@multimethod
def foo(a: int):
    return "an int"

@multimethod
def foo(a: int, b: str):
    return "an int and a string"

if __name__ == '__main__':
    print("foo(1,'a') = {}".format(foo(1,'a')))
    print("foo(7) = {}".format(foo(7)))

작업은 Guido의 원래 게시물에 표시된 대로 유형을 장식자에 추가하여 수행할 수 있지만 매개 변수 자체에 주석을 다는 것이 매개 변수와 유형이 잘못 일치할 가능성을 방지하기 때문에 더 좋습니다.

참고: 파이썬에서 다음과 같이 주석에 액세스할 수 있습니다.function.__annotations__function.func_annotations▁the로서func_*스타일이 Python 3에서 제거되었습니다.

우리당은 이미 적절한 답변을 내놓았기 때문에 여기에 덜 심각한 답변이 있습니다.그래서 당신은 당신의 의사 끈을 더 짧게 만들 수 있습니다.

처음 주석을 보았을 때, 저는 "훌륭해요!"라고 생각했습니다.마침내 저는 몇 가지 유형 검사를 선택할 수 있습니다!" 물론 주석이 실제로 적용되지 않는다는 것을 참조하십시오.

그래서 저는 그것들을 시행하기 위해 간단한 기능 장식자를 쓰기로 결정했습니다.

def ensure_annotations(f):
    from functools import wraps
    from inspect import getcallargs
    @wraps(f)
    def wrapper(*args, **kwargs):
        for arg, val in getcallargs(f, *args, **kwargs).items():
            if arg in f.__annotations__:
                templ = f.__annotations__[arg]
                msg = "Argument {arg} to {f} does not match annotation type {t}"
                Check(val).is_a(templ).or_raise(EnsureError, msg.format(arg=arg, f=f, t=templ))
        return_val = f(*args, **kwargs)
        if 'return' in f.__annotations__:
            templ = f.__annotations__['return']
            msg = "Return value of {f} does not match annotation type {t}"
            Check(return_val).is_a(templ).or_raise(EnsureError, msg.format(f=f, t=templ))
        return return_val
    return wrapper

@ensure_annotations
def f(x: int, y: float) -> float:
    return x+y

print(f(1, y=2.2))

>>> 3.2

print(f(1, y=2))

>>> ensure.EnsureError: Argument y to <function f at 0x109b7c710> does not match annotation type <class 'float'>

확인 라이브러리에 추가했습니다.

질문을 받은 지 오래되었지만 질문에 제시된 예제 스니펫은 (여기서도 언급한 바와 같이) PEP 3107의 것이며, 마지막에 PEP 예제입니다. 또한 PEP의 관점에서 질문에 답할 수 있는 사용 사례도 제시되어 있습니다.;)

다음은 PEP3107에서 인용한 것입니다.

사용 사례

주석을 논의하는 과정에서 여러 가지 사용 사례가 제기되었습니다.이러한 정보 중 일부는 전달되는 정보의 종류에 따라 그룹화되어 여기에 제시됩니다.주석을 사용할 수 있는 기존 제품 및 패키지의 예도 포함됩니다.

  • 입력 정보 제공
    • 유형 확인([3], [4])
    • IDE가 함수가 기대하고 반환하는 유형을 표시하도록 합니다([17]).
    • 기능 오버로딩/일반 기능([22]
    • 외국어 다리 ([18], [19])
    • 적응([21], [20])
    • 술어 논리 함수
    • 데이터베이스 쿼리 매핑
    • RPC 매개 변수 마샬링([23])
  • 다른 정보
    • 매개변수 및 반환 값에 대한 문서화([24])

특정 지점에 대한 자세한 내용은 PEP를 참조하십시오(참고 자료뿐 아니라).

또한 Python 3.X(전용)는 함수 정의를 일반화하여 인수 및 반환 값에 확장에 사용할 개체 을 주석 처리할 수 있도록 합니다.

함수 값에 대해 더 명확하게 설명하기 위한 메타데이터입니다.

은 주은다음같코드니다됩화이과석▁as다로 코딩됩니다.:value에, 인이뒤앞기값으로, 그고리본은 다음과 같이 됩니다.->value인수 목록 뒤에 있습니다.

은 들은다같수이다니됩집으로 .__annotations__함수의 속성이지만 Python 자체에 의해 특별하게 취급되지는 않습니다.

>>> def f(a:99, b:'spam'=None) -> float:
... print(a, b)
...
>>> f(88)
88 None
>>> f.__annotations__
{'a': 99, 'b': 'spam', 'return': <class 'float'>}

출처: 파이썬 포켓 레퍼런스, 5판

예:

typeannotations codemodule Python의 및 도구 집합을 합니다.또한 기능 및 개체에 주석을 다는 데 유용한 유형 집합을 제공합니다.

이러한 도구는 주로 린터, 코드 완성 라이브러리 및 IDE와 같은 정적 분석기에서 사용하도록 설계되었습니다.또한 런타임 체크를 위한 장식기가 제공됩니다.런타임 유형 검사가 Python에서 항상 좋은 생각은 아니지만, 경우에 따라 매우 유용할 수 있습니다.

https://github.com/ceronman/typeannotations

타이핑이 코드 작성에 도움이 되는 방법

타이핑을 사용하면 운영 환경에 코드를 보내기 전에 정적 코드 분석을 수행하여 유형 오류를 탐지하고 몇 가지 명백한 버그를 방지할 수 있습니다.mypy와 같은 도구가 있으며, 소프트웨어 수명 주기의 일부로 도구 상자에 추가할 수 있습니다.mypy는 당신의 코드베이스에 부분적으로 또는 전체적으로 실행함으로써 정확한 유형을 확인할 수 있습니다. mypy는 또한 값이 함수에서 반환될 때 None 유형을 확인하는 것과 같은 버그를 탐지하는 것을 도와줍니다.입력하면 코드를 더 깨끗하게 만들 수 있습니다.문서 문자열에서 유형을 지정하는 주석을 사용하여 코드를 문서화하는 대신 성능 비용 없이 유형을 사용할 수 있습니다.

Clean Python:Python ISBN에서의 우아한 코딩: ISBN-13 (pbk): 978-1-4842-4877-5

PEP 526 -- 변수 주석 구문

https://www.python.org/dev/peps/pep-0526/

https://www.attrs.org/en/stable/types.html

여기에 설명된 모든 용도에도 불구하고 주석을 강제적으로 사용하는 것은 유형 힌트에 대한 것입니다.

이것은 현재 어떤 방식으로든 시행되지 않지만 PEP 484로 판단하면 Python의 향후 버전은 유형만 주석 값으로 허용할 것입니다.

주석의 기존 용도에 대한 인용:

우리는 타입 힌트가 결국 주석의 유일한 사용이 되기를 바라지만, 이를 위해서는 Python 3.5를 사용한 타이핑 모듈의 초기 롤아웃 이후 추가 논의와 사용 중단 기간이 필요합니다.현재 PEP는 Python 3.6이 출시될 때까지 임시 상태(PEP 411 참조)입니다.생각할 수 있는 가장 빠른 체계는 3.6에서 비형 힌트 주석의 무음 사용, 3.7에서 완전한 주석 사용을 도입하고 유형 힌트를 Python 3.8에서 유일하게 허용되는 주석 사용으로 선언할 것입니다.

아직 3.6에서 어떤 무언의 비난도 보지 못했지만, 대신에 이것은 3.7로 떨어질 가능성이 높습니다.

따라서 다른 유용한 사용 사례가 있을 수도 있지만, 이러한 제한이 적용되는 미래에 모든 것을 변경하고 싶지 않다면 유형 암시만을 위해 보관하는 것이 가장 좋습니다.

약간의 지연된 답변으로, 몇몇 패키지(marrow.script, WebCore 등)는 타입캐스팅(즉, 웹에서 들어오는 값을 변환하고 어떤 인수가 부울 스위치인지 탐지하는 등)을 선언하고 추가 인수 마크업을 수행할 수 있는 곳에서 주석을 사용합니다.

Morrow Script는 임의 함수 및 클래스에 대한 완전한 명령줄 인터페이스를 구축하고 주석을 통해 문서, 캐스팅 및 콜백 파생 기본값을 정의할 수 있도록 하며 이전 런타임을 지원하는 데코레이터를 사용합니다.주석을 사용하는 모든 라이브러리는 다음 양식을 지원합니다.

any_string  # documentation
any_callable  # typecast / callback, not called if defaulting
(any_callable, any_string)  # combination
AnnotationClass()  # package-specific rich annotation object
[AnnotationClass(), AnnotationClass(), …]  # cooperative annotation

문서 문자열 또는 유형 캐스팅 기능에 대한 "베어" 지원을 통해 주석 인식 라이브러리와 더 쉽게 혼합할 수 있습니다. (즉, 명령 줄 스크립트로도 노출되는 유형 캐스팅을 사용하는 웹 컨트롤러가 있어야 합니다.)

추가할 편집 내용:저는 또한 검증을 위해 개발 시간 어설션을 사용하는 TypeGuard 패키지를 사용하기 시작했습니다.이점: "최적화"를 사용하도록 설정한 상태에서 실행할 경우(-O/PYTHONOPTIMIZE을 제대로 envar에서 검사가 들 수 검사

주석은 코드를 쉽게 모듈화하는 데 사용할 수 있습니다.예를 들어, 내가 관리하는 프로그램의 모듈은 다음과 같은 방법을 정의할 수 있습니다.

def run(param1: int):
    """
    Does things.

    :param param1: Needed for counting.
    """
    pass

그리고 사용자에게 "param1"이라는 이름의 "param1"을 요청할 수 있습니다. "계산에 필요한" 항목은 "int"여야 합니다.결국 우리는 사용자가 준 문자열을 원하는 유형으로 변환하여 가장 번거롭지 않은 경험을 얻을 수 있습니다.

이에 도움이 되고 필요한 값을 자동으로 검색하여 원하는 유형으로 변환할 수 있는 오픈 소스 클래스에 대한 함수 메타데이터 개체를 참조하십시오(주석이 변환 방법이기 때문).IDE도 자동 완성이 올바르고 유형이 주석에 따른다고 가정합니다. 즉, 완벽하게 적합합니다.

Cython의 장점 목록을 보면 컴파일러가 Python 객체의 유형을 알려주는 기능이 가장 중요합니다.

저는 Cython(또는 Python 코드의 일부를 컴파일하는 유사한 도구)이 주석 구문을 사용하여 마법을 수행하는 미래를 상상할 수 있습니다.

언급URL : https://stackoverflow.com/questions/3038033/what-are-good-uses-for-python3s-function-annotations

반응형