Python类型提示语法如何/为何起作用?

时间:2015-04-21 11:04:59

标签: python python-3.x type-hinting pep

我刚看到PEP 484中的以下示例:

def greeting(name: str) -> str:
    return 'Hello ' + name

print(greeting('Martin'))
print(greeting(1))

正如所料,这在Python 2中不起作用:

  File "test.py", line 1
    def greeting(name: str) -> str:
                     ^
SyntaxError: invalid syntax

但是,它适用于Python 3:

Hello Martin
Traceback (most recent call last):
  File "test.py", line 5, in <module>
    print(greeting(1))
  File "test.py", line 2, in greeting
    return 'Hello ' + name
TypeError: Can't convert 'int' object to str implicitly

这是出乎意料的。它还没有真正检查类型,你可以看到以下示例(它运行,但不会抛出异常):

def greeting(name: str) -> int:
    return 'Hello ' + name

print(greeting('Martin'))

似乎在:之后必须是函数的名称,但函数似乎被忽略了:

def aha(something):
    print("aha")
    return something+"!"

def greeting(name: aha, foo) -> int:
    return 'Hello ' + name + foo

print(greeting('Martin', 'ad'))

->之后的名称似乎也是如此。

这种类型的提示语法是否使用了其他东西(比如Java Modeling语言使用了注释)?这个语法是什么时候引入Python的?有没有办法用这个语法进行静态类型检查?它总是会破坏Python 2的兼容性吗?

1 个答案:

答案 0 :(得分:29)

此处没有类型提示。你所做的只是提供注释;这些是PEP 3107引入的(仅在Python 3中,Python 2中不支持这种情况);它们允许您注释参数并使用任意信息返回值以供以后检查:

>>> greeting.__annotations__
{'name': <class 'str'>, 'return': <class 'str'>}

在这里,他们根本没有被咨询过。相反,您得到的错误消息是尝试在函数体中连接字符串和整数值

>>> 'Hello ' + 1
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: Can't convert 'int' object to str implicitly

这是一个自定义类型错误,旨在提供有关str + int连接失败的原因的其他信息;对于任何非str.__add__的类型,str方法都会抛出它:

>>> ''.__add__(1)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: Can't convert 'int' object to str implicitly
>>> ''.__add__(True)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: Can't convert 'bool' object to str implicitly
然后,PEP 484建议使用这些注释来使用附加工具进行实际的静态类型检查,但是随着PEP的引入说明:

  

虽然这些注释在运行时通过通常的__annotations__属性可用,但在运行时没有进行类型检查。相反,该提议假定存在一个单独的离线类型检查器,用户可以自动运行其源代码。从本质上讲,这种类型的检查器就像一个非常强大的linter。

强调原作。

PEP的灵感来自使用PEP 3107注释的现有工具;特别是mypy project(通过采用PEP 484循环回来),还有type hinting support in the PyCharm IDEpytypedecl project。见Guido van Rossum的original email kickstarting this effort以及follow-up email

mypy通过预处理注释显然支持Python 2,在为您编译源代码之前删除它们,但是否则通常不能使用Python代码在Python 2中工作的语法。

PEP 484还描述了stub files的使用,它位于常规Python文件的旁边;这些使用.pyi扩展名,只包含签名(带有类型提示),保留主.py个文件注释,因此可以在Python 2上使用(前提是你编写了Polyglot Python代码)。