문제

나는 내가 원했던 것만큼 Python 3의 개발에 많은 관심을 기울이지 않았고 단지 몇 가지 흥미로운 새로운 구문 변경 사항을 발견했습니다.구체적으로 이 SO 답변 함수 매개변수 주석:

def digits(x:'nonnegative number') -> "yields number's digits":
    # ...

이것에 대해 아무것도 몰랐기 때문에 Python에서 정적 타이핑을 구현하는 데 사용될 수 있을 것이라고 생각했습니다!

검색을 좀 해보니 (완전히 선택적인) Python의 정적 타이핑에 관해 많은 논의가 있었던 것 같습니다. PEP 3107, 그리고 "Python에 선택적 정적 유형 추가" (그리고 2 부)

..하지만 이것이 얼마나 진행되었는지는 확실하지 않습니다.매개변수 주석을 사용하여 정적 유형 지정 구현이 있습니까?매개변수화된 유형의 아이디어 중 어떤 것이 Python 3에 포함되었나요?

도움이 되었습니까?

해결책

내 코드를 읽어 주셔서 감사합니다!

실제로, 파이썬에서 일반적인 주석 집행자를 만드는 것은 어렵지 않습니다. 내 테이크는 다음과 같습니다.

'''Very simple enforcer of type annotations.

This toy super-decorator can decorate all functions in a given module that have 
annotations so that the type of input and output is enforced; an AssertionError is
raised on mismatch.

This module also has a test function func() which should fail and logging facility 
log which defaults to print. 

Since this is a test module, I cut corners by only checking *keyword* arguments.

'''

import sys

log = print


def func(x:'int' = 0) -> 'str':
    '''An example function that fails type checking.'''
    return x


# For simplicity, I only do keyword args.
def check_type(*args):
    param, value, assert_type = args
    log('Checking {0} = {1} of {2}.'.format(*args))
    if not isinstance(value, assert_type):
        raise AssertionError(
            'Check failed - parameter {0} = {1} not {2}.'
            .format(*args))
    return value

def decorate_func(func):    
    def newf(*args, **kwargs):
        for k, v in kwargs.items():
            check_type(k, v, ann[k])
        return check_type('<return_value>', func(*args, **kwargs), ann['return'])

    ann = {k: eval(v) for k, v in func.__annotations__.items()}
    newf.__doc__ = func.__doc__
    newf.__type_checked = True
    return newf

def decorate_module(module = '__main__'):
    '''Enforces type from annotation for all functions in module.'''
    d = sys.modules[module].__dict__
    for k, f in d.items():
        if getattr(f, '__annotations__', {}) and not getattr(f, '__type_checked', False):
            log('Decorated {0!r}.'.format(f.__name__))
            d[k] = decorate_func(f)


if __name__ == '__main__':
    decorate_module()

    # This will raise AssertionError.
    func(x = 5)

이 단순성을 감안할 때, 첫눈에 이상적 으로이 일이 주류가 아님이 이상합니다. 그러나 나는 그것이 왜 보이는 것만 큼 유용하지 않습니다. 일반적으로 유형 검사는 정수와 사전을 추가하면 명백한 실수를 저지르기 때문에 도움이되기 때문에 도움이됩니다 (그리고 합리적인 것을 의미한다면 여전히 그렇습니다. 암시적인 것보다 명시적인 것이 낫습니다).

그러나 실생활에서 당신은 종종 같은 양을 섞습니다. 컴퓨터 유형 컴파일러에서 볼 수 있지만 명확하게 다릅니다 인간 유형, 예를 들어 다음 스 니펫에는 명백한 실수가 포함되어 있습니다.

height = 1.75 # Bob's height in meters.
length = len(sys.modules) # Number of modules imported by program.
area = height * length # What's that supposed to mean???

모든 인간은 위에서 즉시 실수를보아야합니다. '인간 유형'변수를 알고 있다면 height 그리고 length 컴퓨터로 보이지만 완벽하게 합법적입니다 곱셈 int 그리고 float.

이 문제에 대한 가능한 해결책에 대해 더 많은 말을 할 수 있지만 '컴퓨터 유형'을 시행하는 것은 분명히 반 솔루션이므로 적어도 제 생각에는 해결책이 전혀없는 것보다 더 나쁘다. 같은 이유입니다 시스템 헝가리어 한편 끔찍한 아이디어입니다 앱 헝가리어 훌륭한 것입니다. 매우 유익한 사람들이 더 있습니다 Joel Spolsky의 게시물.

이제 누군가가 실제 데이터에 자동으로 할당하는 일종의 Pythonic 타사 라이브러리를 구현한다면 인간 유형 그런 다음 그런 유형을 변환하기 위해주의를 기울였습니다 width * height -> area 그리고 그 기능 주석으로 확인하면 사람들이 실제로 사용할 수있는 유형이라고 생각합니다!

다른 팁

PEP에서 언급했듯이, 정적 유형 검사는 기능 주석을 사용할 수있는 가능한 응용 프로그램 중 하나이지만,이를 수행하는 방법을 결정하기 위해 타사 라이브러리까지 남겨 둡니다. 즉, Core Python에는 공식적인 구현이 없을 것입니다.

타사 구현에 관한 한, 일부 스 니펫이 있습니다 (예 : http://code.activestate.com/recipes/572161/), 그것은 일을 잘하는 것 같습니다.

편집하다:

참고로, 나는 동작을 확인하는 것이 유형을 확인하는 것이 바람직하다는 것을 언급하고 싶습니다. 따라서 정적 유형이 아이디어는 그다지 큰 아이디어가 아니라고 생각합니다. 위의 대답은 그런 식으로 자신을 타이핑하기 때문에 질문에 대답하는 것을 목표로합니다.

이것은 직접적인 질문에 대한 답변은 아니지만 정적 타이핑을 추가하는 Python 포크를 발견했습니다. mypy-lang.org, 물론 아직은 작은 노력이지만 흥미롭기 때문에 의존할 수는 없습니다.

파이썬의 "정적 타이핑"은 유형 확인이 런타임으로 수행되도록 만 구현할 수 있으므로 응용 프로그램이 느려집니다. 그러므로 당신은 그것을 일반성으로 원하지 않습니다. 대신 입력을 확인하는 몇 가지 방법을 원합니다. 이것은 평범한 주장으로 쉽게 이루어질 수 있습니다.

정적 유형 확인에 대한 대안이 있으며 이는 Zope 구성 요소 아키텍처와 같은 측면 지향성 구성 요소 아키텍처를 사용하는 것입니다. 유형을 확인하는 대신 적응합니다. 그래서 대신 :

assert isinstance(theobject, myclass)

당신은 이것을합니다 :

theobject = IMyClass(theobject)

TheObject가 이미 Imyclass를 구현하면 아무 일도 일어나지 않습니다. 그렇지 않은 경우, TheObject에있는 모든 것을 IMyclass에 감싸는 어댑터는 theObject 대신에 사용되어 사용됩니다. 어댑터가 없으면 오류가 발생합니다.

이것은 Python의 역학을 특정한 방식으로 특정 유형을 갖고자하는 욕구와 결합했습니다.

물론, 정적 타이핑은 약간 "unpythonic"인 것처럼 보이며 항상 그것을 사용하지 않습니다. 그러나 실제로 개발 속도를 높일 수있는 사례 (예 : 도메인 별 언어 구문 분석)가 있습니다.

그런 다음 사용하는 것을 선호합니다 Beartype 이것에 대해 설명했다 게시하다*. 그것은 git repo, 테스트 및 그것이 할 수있는 것과 그것이 할 수없는 일을 설명합니다 ... 그리고 나는 이름을 좋아합니다;)

*이 경우 Python에 배터리가 포함되어 있지 않은 이유에 대한 Cecil의 분노에주의를 기울이지 마십시오.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top