【问题标题】:Examples of open-source projects using Python 3 function annotations使用 Python 3 函数注解的开源项目示例
【发布时间】:2011-03-14 14:21:55
【问题描述】:

谁能给我一些使用 Python 3 中引入的函数注释的 Python 开源项目示例?

我想看看这个功能的一些实际用途,看看我是否可以在我自己的项目中使用它。

【问题讨论】:

    标签: python-3.x


    【解决方案1】:

    我从未见过在野外使用此功能。但是,我在为USENIX ;Login: 撰写的一篇关于 Python 3 的文章中探讨了函数注释的一个潜在用途,即用于执行合同。例如,您可以这样做:

    from functools import wraps
    
    def positive(x):
        'must be positive'
        return x > 0
    
    def negative(x):
        'must be negative'
        return x < 0
    
    def ensure(func):
        'Decorator that enforces contracts on function arguments (if present)'
        return_check = func.__annotations__.get('return',None)
        arg_checks = [(name,func.__annotations__.get(name))
                       for name in func.__code__.co_varnames]
    
        @wraps(func)
        def assert_call(*args):
            for (name,check),value in zip(arg_checks,args):
                if check: 
                    assert check(value),"%s %s" % (name, check.__doc__)
            result = func(*args)
            if return_check:
                assert return_check(result),"return %s" % (return_check.__doc__)
            return result
        return assert_call
    
    # Example use
    @ensure
    def foo(a:positive, b:negative) -> positive:
        return a-b
    

    如果你这样做,你会看到这样的行为:

    >>> foo(2,-3)
    5
    >>> foo(2,3)
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "ensure.py", line 22, in assert_call
        assert check(value),"%s %s" % (name, check.__doc__)
    AssertionError: b must be negative
    

    我应该注意到,上面的示例需要进一步充实,才能与默认参数、关键字参数和其他细节一起正常工作。这只是一个想法的草图。

    现在,这是否是一个好主意,我只是不知道。我倾向于同意 Brandon 的观点,即缺乏可组合性是一个问题——特别是如果注释开始被不同的库用于不同的目的。我还想知道是否不能通过装饰器来完成类似这种合同想法的事情。例如,制作一个像这样使用的装饰器(实现留作练习):

    @ensure(a=positive,b=negative)
    def foo(a,b):
        return a-b
    

    历史记录,我一直觉得函数注释是 Python 社区 10 多年前关于“可选静态类型”讨论的产物。这是否是最初的动机,我只是不知道。

    【讨论】:

      【解决方案2】:

      我会玩脾气暴躁,并建议不要使用该功能。希望有一天它会被删除。到目前为止,Python 在部署有吸引力、正交且可以堆叠的特性方面做得很好——函数装饰器就是一个很好的例子:如果我使用三个不同的库都希望我装饰我的函数,结果看起来相当干净:

      @lru_cache(max_items=5)
      @require_basic_auth
      @view('index.html')
      def index(…):
          ⋮
      

      但是这个新奇的笨拙的“注释”功能将 Python 带到了相反的方向:因为你只能对给定的函数进行一次精确的注释,它完全破坏了从各个部分组合解决方案的能力。如果您有两个库,每个库都希望您代表它们注释相同的函数,那么据我所知,您将完全受阻。

      【讨论】:

      • 我不明白“注释相同的功能”是什么意思?目的是在定义上注释函数。函数定义只发生一次。它是告诉用户关于它的功能的事情。我不明白你为什么要注释别人定义的函数。
      • Lennart — 我的意思是,如果你想使用库 A 来进行类型检查(就像“typecheck”模块对装饰器所做的那样)并坚持使用注释来这样做;并且您还想使用库 B 来记录对函数的调用,但坚持要对函数进行注释,以便它知道要在日志中包含哪些属性。如果这是你的情况,那么你就被困住了!你想为两个库“注释同一个函数”(我想我的意思是“注释一个函数”)两次,你不能这样做。
      • 啊,你想在同一个函数上放两个注解,是的,这行不通。 +1 的解释。
      猜你喜欢
      • 1970-01-01
      • 2010-10-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-28
      • 1970-01-01
      相关资源
      最近更新 更多