복붙노트

[PYTHON] 파이썬 3의 "함수 주석"

PYTHON

파이썬 3의 "함수 주석"

기능 주석 : PEP-3107

Python3의 함수 주석을 보여주는 코드 스 니펫을 살펴 보았습니다. 개념은 간단하지만 파이썬 3이나 파이썬 3에서 이들을 구현 한 이유를 생각할 수 없습니다. 아마 그래서 나에게 계몽 수 있습니까?

작동 원리 :

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

인수 뒤에 콜론 다음에 오는 모든 것은 '주석'이며, -> 다음에 나오는 정보는 함수의 반환 값에 대한 주석입니다.

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

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

이것을 사용할 수있게 된 이유는 무엇입니까?

해결법

  1. ==============================

    1.나는 이것이 실제로 위대한 것이라고 생각한다.

    나는 이것이 실제로 위대한 것이라고 생각한다.

    학문적 배경에서 볼 때 필자는 Java와 같은 언어의 스마트 정적 분석기를 사용하기 위해 주석이 귀중하다는 것을 입증했다고 말할 수 있습니다. 예를 들어, 상태 제한, 액세스가 허용 된 스레드, 아키텍처 제한 등과 같은 의미를 정의 할 수 있으며, 컴파일러에서 얻은 것 이상의 보장을 제공하기 위해 이들을 읽고 처리 할 수있는 도구가 많이 있습니다. 심지어 전제 조건 / 사후 조건을 확인하는 것을 쓸 수도 있습니다.

    필자는 파이썬에서 특히 약한 타이핑 때문에이 것이 필요하다고 생각합니다. 그러나 공식 구문의이 부분을 간단하게 만들어주는 구조체는 실제로 없었습니다.

    보증 이상의 주석에는 다른 용도가 있습니다. Java 기반 도구를 Python에 적용하는 방법을 알 수 있습니다. 예를 들어, 메소드에 특별한 경고를 할당 할 수있는 도구가 있는데, 문서를 읽어야 할 때 (예 : 음수 값으로 호출하면 안되는 메소드가 있다고 가정하면 표시 할 수 있습니다. 이름에서 직관적이지 않음). 주석을 사용하면 파이썬에서 이와 비슷한 것을 기술적으로 작성할 수 있습니다. 마찬가지로 공식 구문이있는 경우 태그를 기반으로 대형 클래스의 메서드를 구성하는 도구를 작성할 수 있습니다.

  2. ==============================

    2.기능 주석은 사용자가 작성한 것입니다.

    기능 주석은 사용자가 작성한 것입니다.

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

    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/를 참조하십시오.

  3. ==============================

    3.이것은 늦은 대답이지만, 현재 AFAICT는 PEP-0484와 MyPy입니다.

    이것은 늦은 대답이지만, 현재 AFAICT는 PEP-0484와 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
    
  4. ==============================

    4.제 대답에서 좋은 사용에 대한 구체적인 예제를 추가하기 만하면 데코레이터와 함께 멀티 메소드의 간단한 메커니즘을 수행 할 수 있습니다.

    제 대답에서 좋은 사용에 대한 구체적인 예제를 추가하기 만하면 데코레이터와 함께 멀티 메소드의 간단한 메커니즘을 수행 할 수 있습니다.

    # 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.func_annotations가 아닌 function .__ annotations__으로 주석에 액세스 할 수 있습니다. func_ * 스타일은 Python 3에서 제거 되었기 때문입니다.

  5. ==============================

    5.우리는 이미 적절한 대답을 주었으므로 덜 심각한 것이 있습니다. 따라서 문서화 문자열을 짧게 만들 수 있습니다.

    우리는 이미 적절한 대답을 주었으므로 덜 심각한 것이 있습니다. 따라서 문서화 문자열을 짧게 만들 수 있습니다.

  6. ==============================

    6.처음 주석을 보았을 때, "멋지다!"마지막으로 몇 가지 유형 검사를 선택할 수 있습니다! " 물론 주석을 실제로 적용하지 않는다는 것을 알지 못했습니다.

    처음 주석을 보았을 때, "멋지다!"마지막으로 몇 가지 유형 검사를 선택할 수 있습니다! " 물론 주석을 실제로 적용하지 않는다는 것을 알지 못했습니다.

    그래서 나는 그것들을 시행 할 간단한 함수 데코레이터를 작성하기로 결정했다.

    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'>
    

    나는 그것을 Ensure 라이브러리에 추가했다.

  7. ==============================

    7.이 질문 이후 오랜 시간이 걸렸지 만 질문에 주어진 예시 발췌 문장은 PEP 3107의 PEP 예제와 PEP 예제의 끝 부분에 나와 있습니다 (예 : PEP 3107). 보기;)

    이 질문 이후 오랜 시간이 걸렸지 만 질문에 주어진 예시 발췌 문장은 PEP 3107의 PEP 예제와 PEP 예제의 끝 부분에 나와 있습니다 (예 : PEP 3107). 보기;)

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

    사용 사례

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

    특정 포인트 (및 참조 번호)에 대한 자세한 정보는 PEP를 참조하십시오.

  8. ==============================

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

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

    Marrow 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
    

    docstring이나 typecasting 함수에 대한 "Bare"지원은 주석을 인식하는 다른 라이브러리와 쉽게 섞을 수있게합니다. (즉, typecasting을 사용하는 웹 컨트롤러가 명령 행 스크립트로 노출 될 수도 있습니다.)

  9. ==============================

    9.여기에 설명 된 모든 용도에도 불구하고 주석을 적용 할 수 있고 적용 가능성이 높은 유형 힌트는 유형 힌트입니다.

    여기에 설명 된 모든 용도에도 불구하고 주석을 적용 할 수 있고 적용 가능성이 높은 유형 힌트는 유형 힌트입니다.

    이것은 현재 어떤 식 으로든 강제되지는 않지만 PEP 484에서 판단 할 때, 파이썬의 미래 버전은 타입을 주석의 가치로만 허용 할 것입니다.

    인용하기 주석의 기존 용도는 어떻습니까?

    아직 3.6에서 침묵하는 비난을 보지 못했지만, 이것은 3.7으로 대체 될 수 있습니다.

    따라서 다른 유용한 유스 케이스가있을지라도이 제한이있는 미래의 모든 것을 바꾸고 싶지 않으면 유형 힌트를 위해 유스 케이스를 유지하는 것이 가장 좋습니다.

  10. ==============================

    10.Python 3.X (only)는 또한 함수 정의를 일반화하여 객체 값으로 주석을 붙일 인수와 반환 값 확장에 사용하기 위해.

    Python 3.X (only)는 또한 함수 정의를 일반화하여 객체 값으로 주석을 붙일 인수와 반환 값 확장에 사용하기 위해.

    설명 할 META 데이터는 함수 값에 대해보다 명확하게 설명합니다.

    주석은 다음과 같이 코딩됩니다. 인수 이름과 기본값 앞에 있고, as -> 값은 인수 목록.

    그것들은 함수의 __annotations__ 속성으로 수집되지만, 파이썬 자체에 의해 특별한 것으로 취급되지 않습니다 :

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

    예:

    typeannotations 모듈은 유형 검사와 Python 코드의 유형 유추를위한 일련의 도구를 제공합니다. 또한 함수 및 객체에 주석을다는 데 유용한 유형 집합을 제공합니다.

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

    https://github.com/ceronman/typeannotations

  11. ==============================

    11.주석을 사용하면 코드를 쉽게 모듈화 할 수 있습니다. 예 : 내가 유지하고있는 프로그램을위한 모듈은 다음과 같은 메소드를 정의 할 수있다 :

    주석을 사용하면 코드를 쉽게 모듈화 할 수 있습니다. 예 : 내가 유지하고있는 프로그램을위한 모듈은 다음과 같은 메소드를 정의 할 수있다 :

    def run(param1: int):
        """
        Does things.
    
        :param param1: Needed for counting.
        """
        pass
    

    우리는 사용자에게 "계산에 필요한"param1이라는 것을 요청할 수 있으며 "int"여야합니다. 마지막으로 우리는 사용자가 입력 한 문자열을 원하는 유형으로 변환하여 가장 번거로운 사용 경험을 얻을 수도 있습니다.

    이 기능을 지원하고 필요한 값을 자동으로 검색하여 원하는 모든 유형으로 변환 할 수있는 오픈 소스 클래스에 대한 함수 메타 데이터 객체를 참조하십시오 (주석이 변환 메소드이기 때문에). IDE조차도 자동 완성을 올바르게 보여 주며 유형이 주석에 따라 완벽하게 맞다고 가정합니다.

  12. ==============================

    12.Cython의 장점 목록을 살펴보면, 파이썬 객체가 어떤 유형인지를 컴파일러에 알리는 기능이 주요 기능 중 하나입니다.

    Cython의 장점 목록을 살펴보면, 파이썬 객체가 어떤 유형인지를 컴파일러에 알리는 기능이 주요 기능 중 하나입니다.

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

  13. from https://stackoverflow.com/questions/3038033/what-are-good-uses-for-python3s-function-annotations by cc-by-sa and MIT license