为什么函数注释需要Python中的专用语法?

D K*_*D K 5 python syntax python-3.x

函数注释似乎重复已在Python中找到的行为.不仅如此,它们所采用的含义并未以任何方式强制执行,因此它们可用于PEP 3107中记录的以下任何内容:

  • 提供打字信息
  • 类型检查
  • 让IDE显示函数期望和返回的类型
  • 函数重载/泛型函数
  • 外语桥梁
  • 适应
  • 谓词逻辑功能
  • 数据库查询映射
  • RPC参数编组
  • 其他信息
  • 参数和返回值的文档

甚至是完全不同的东西.

在某种程度上,函数注释让我想起Python的幽默集合中的旧笑话:

事实上,Python已经支持块分隔符:

>
>     if foo: #{
>         foo1();
>         foo2();
>         foo3();
>     #}
Run Code Online (Sandbox Code Playgroud)

在那里面

def foo(a: 'x', b: 5 + 6, c: list) -> max(2, 9):
    ...
Run Code Online (Sandbox Code Playgroud)

没有比以下更有帮助了:

# a: 'x', b: 5 + 6, c: list
def foo(a, b, c):  #-> max(2, 9):
    ...
Run Code Online (Sandbox Code Playgroud)

有人可能认为函数注释是必要的,因为与注释不同,它们可以在代码中访问,例如:

>>> def spam(a: 'eggs') -> 'ni!':
...     pass
...
>>> spam.__annotations__
{'a': 'eggs', 'return': 'ni!'}
Run Code Online (Sandbox Code Playgroud)

虽然使用装饰器可以很容易地实现相同的行为,例如:

def param(**kw):
    def decorator(func):
        def wrap(*args):
            print kw
            func(*args)
        return wrap
    return decorator

def return_(arg):
    def decorator(func):
        def wrap(*args):
            func(*args)
            print arg
        return wrap
    return decorator

@param(a='eggs')
@return_('ni!')
def spam(a):
    pass

spam(None)

# Output:
# -------
## {'a': 'eggs'}
## ni!
Run Code Online (Sandbox Code Playgroud)

Python已经可以做注释了,为什么函数注释需要专用语法?

编辑:我将在我的问题上做一些扩展,因为它的含义已经证明有点不清楚.

我问这个问题具体是关于函数注释而不是装饰器,其中

@decorator
def spam():
    pass
Run Code Online (Sandbox Code Playgroud)

是的缩写

def spam():
    pass
spam = decorator(spam)
Run Code Online (Sandbox Code Playgroud)

和方法调用,在哪里

self.method(param)
Run Code Online (Sandbox Code Playgroud)

是的缩写

Class.method(self, param)
Run Code Online (Sandbox Code Playgroud)

使用这两种速记句法快捷键,它们的含义不会有所不同.我不是问为什么在有预先存在的替代品时这些捷径是必要的; 这是一个可读性的问题.功能注释与这两个快捷方式略有不同

def spam() -> int:
    pass
Run Code Online (Sandbox Code Playgroud)

def spam() -> 'integer':
    pass
Run Code Online (Sandbox Code Playgroud)

可能与人类具有相同的含义,但与计算机的含义不同.即使程序员知道注释应该定义什么,也没有就注释如何定义注释的定义达成一致.此外,注释不会影响功能,因此不需要保持一致.

所以这是我修改过的问题:

为什么功能注释在提供可更改且可能不一致的访问现有语言功能的方式时需要专用语法?为什么会出现上没有强制的定义如何使用注释,当有一个完美的定义是什么,他们可以用于(PEP 3107)?

ret*_*ile 6

您链接到的PEP 3107似乎在其"基本原理"部分提供了您的问题的答案:

合理

因为Python的2.x系列缺乏注释函数参数和返回值的标准方法,所以各种工具和库似乎已经填补了这个空白.有些人利用"PEP 318"中引入的装饰器,而其他人则解析函数的文档字符串,在那里寻找注释.

该PEP旨在提供一种指定此信息的单一标准方法,从而减少由此之前存在的机制和语法的广泛变化引起的混淆.


Win*_*ert 6

装饰器语法的重点是什么?它不允许您做任何以前不能做的事情:

@staticmethod
def foo():
    pass
Run Code Online (Sandbox Code Playgroud)

只是

def foo():
    pass
foo = staticmethod(foo)
Run Code Online (Sandbox Code Playgroud)

但装饰器语法更好.

其中两个更好:

@param(a='eggs')
@return_('ni!')
def spam(a):
    pass

def spam(a: 'eggs') -> 'ni!':
    pass
Run Code Online (Sandbox Code Playgroud)

意见可能有所不同,但我认为第二个更好.