读者是否发现,在前述所写过的函数中,对参数的类型——形参应该引用什么类型的实参——没有要求声明,也没有在函数中检查类型。比如编写一个实现加法的函数:
>>> def add(x, y): return x+y
...
因为在函数体内只有一条语句,所以可以写成一行。
用下面的方式调用此函数:
>>> add(3, 4)
7
>>> add('learn', 'python')
'learnpython'
>>> add([1,2,3], [4,5,6])
[1, 2, 3, 4, 5, 6]
分别让 add()
的形参 x, y
引用了不同类型的 Python 对象,只要它们能够执行 “ +
” 运算符,函数就能正常执行,且返回值的类型也各不相同。这就是 Python 中函数的特点(这种特征在第8章8.6节会深入探讨):
当然,这个特点有时候会带来一点点麻烦,比如:
>>> add(4, 'book')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 1, in add
TypeError: unsupported operand type(s) for +: 'int' and 'str'
由于不强制参数类型,如果按照上述方式调用函数,就会报出异常。此类问题将运用第10章10.2节中所介绍的方法给予处理。
Python 为了照顾有其他编程语言习惯的开发者,以及“追求明确的强迫症”开发者,允许在定义函数的时候,对参数和函数返回值的类型给予说明。
>>> def new_add(x:int, y:int)->int:
... return x + y
...
>>> new_add(2, 4)
6
但是,这也只是“君子协定”和必要注释,旨在告知或者提醒开发者,而非强制执行,即使不遵守“君子协定”,只要符合 Python 语法,也依然“通行无阻”。
>>> new_add('book', 'python')
'bookpython'
更甚者,还可以在定义函数时用类似形式对各参数及返回值给予更多注释,这并非总是画蛇添足,例如:
>>> def kinetic_energy(m:'in kg', v:'in m/s')->'Joules':
... return (m*v**2)/2
...
>>> kinetic_energy(10, 2)
20.0
这里定义了一个计算物体动能的函数 kinetic_energy()
。在物理量的计算中,特别强调单位。在定义此函数时,就以 m:'in kg'
的方式明确声明物体质量的单位——虽然也不是强制,但是提醒使用此函数的人,只有按照此处规定的单位制,才得到以焦耳( Joules )为单位的动能。
最后声明,是否要在函数中使用上述形式注释,根据具体情形而定。