Python 的函数注解功能允许你在函数定义中声明的参数添加额外的解释性元数据,并且还可以指定返回的数据类型。它们在函数执行过程中不会被 Python 解释器考虑。主要目的是为了提供详细的文档给 Python 集成开发环境(IDE)中的程序员。
尽管你可以使用 Python 的 docstring 特性来记录函数,但如果函数原型发生了某些变化,docstring 可能会变得过时。因此,作为 PEP 3107 的结果,Python 引入了注解特性。
注解可以是任何有效的 Python 表达式,并且可以附加到参数或返回数据类型上。最简单的注解示例是规定参数的数据类型。注解是在参数前面加上冒号之后作为一个表达式来表示的。
示例
请记住,Python 是一种动态类型的语言,在运行时不会强制类型检查。因此,即使在调用函数时提供了非整数参数,Python 也不会检测到任何错误。
def myfunction(a: int, b: int):
c = a + b
return c
print(myfunction(10, 20))
print(myfunction("Hello ", "Python"))
它将产生以下输出:
30
Hello Python
带有返回类型的函数注解
注解在运行时会被忽略,但对于 IDE 和静态类型检查库如 mypy 十分有用。
你也可以为返回数据类型提供注解。在括号后面和冒号符号之前,放置一个箭头(->),然后跟上注解。
示例
在这个例子中,我们为返回类型提供了注解。
def myfunction(a: int, b: int) -> int:
c = a + b
return c
print(myfunction(56, 88))
print(myfunction.__annotations__)
这将生成以下输出:
144
{'a': <class 'int'>, 'b': <class 'int'>, 'return': <class 'int'>}
带有表达式的函数注解
由于将数据类型作为注解在运行时会被忽略,因此你可以将任何表达式作为参数的元数据。因此,函数可以有任意的表达式作为注解。
示例
在下面的例子中,我们使用表达式作为函数注解。
def total(x : 'Physics 成绩', y: 'Chemistry 成绩'):
return x + y
print(total(86, 88))
print(total.__annotations__)
以下是输出:
174
{'x': 'Physics 成绩', 'y': 'Chemistry 成绩'}
带默认参数的函数注解
如果你想在注解的同时指定默认参数,你需要在注解表达式之后放置它。默认参数必须在参数列表中的必需参数之后出现。
示例 1
下面的例子展示了如何为函数的默认参数提供注解。
def myfunction(a: "Physics", b: "Maths" = 20) -> int:
c = a + b
return c
print(myfunction(10))
Python 中的函数也是一个对象,其中一个属性就是 __annotations__
。你可以通过 dir()
函数来检查它。
print(dir(myfunction))
这将打印包含 __annotations__
属性的 myfunction
对象的列表。
['__annotations__', '__builtins__', '__call__', '__class__', '__closure__', '__code__', '__defaults__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__get__', '__getattribute__', '__getstate__', '__globals__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__kwdefaults__', '__le__', '__lt__', '__module__', '__name__', '__ne__', '__new__', '__qualname__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__']
示例 2
__annotations__
属性本身是一个字典,其中参数是键而注解是值。
def myfunction(a: "Physics", b: "Maths" = 20) -> int:
c = a + b
return c
print(myfunction.__annotations__)
它将产生以下输出:
{'a': 'Physics', 'b': 'Maths', 'return': <class 'int'>}
示例 3
如果你需要为函数提供任意位置参数和/或任意关键字参数,也可以为它们提供注解。
def myfunction(*args: "任意参数", **kwargs: "任意关键字参数") -> int:
pass
print(myfunction.__annotations__)
它将产生以下输出:
{'args': '任意参数', 'kwargs': '任意关键字参数', 'return': <class 'int'>}
示例 4
如果你需要为函数参数提供多于一个的注解表达式,可以在参数前以字典的形式提供它。
def division(num: dict(type=float, msg='分子'), den: dict(type=float, msg='分母')) -> float:
return num / den
print(division.__annotations__)
它将产生以下输出:
{'num': {'type': <class 'float'>, 'msg': '分子'}, 'den': {'type': <class 'float'>, 'msg': '分母'}, 'return': <class 'float'>}