在Python中定义函数非常简单,下面是一个简单的例子,该函数的功能就是打印“Hello World!”。
def Hello(): # def关键字是用来定义函数的
print("Hello World!") # 函数体需要缩进。
Hello是函数名称,紧跟着Hello的是括号,括号里面是函数的参数,不管参数有没有,括号一定要有。然后就是冒号,标志着一段新的代码段要开始了。通常,我们还会在函数的代码段开始的地方写上文档字符串,来描述函数是用来干什么的。例如下面的例子:
def add(x, y): # 两个参数
"""计算变量x和y之和""" # 文档字符串
return x + y # 返回值
这个函数不同于前面的函数之处是,该函数拥有了两个参数,并且还拥有了返回值。这些东西看起来和C语言是基本一致的,只不过Python是动态语言,无需指明返回值的数据类型。当然了,使用方式也和C语言没有什么区别。你只需要在你想使用它的地方调用它即可。例如:
def add(x, y): # 两个参数
"""计算变量x和y之和""" # 文档注释
return x + y # 返回值
sum = add(123,456)
print(sum)
程序执行结果如下所示:
也就是说,你只要知道了上面的点之后,就可以在Python中使用函数了,只是这样的函数可能带着非常浓厚的C语言的气息。Python的函数支持关键字实参,从而可以忽略参数参数传递的顺序,例如:
def add(x, y): # 两个参数
"""计算变量x和y之和""" # 文档注释
return x + y # 返回值
sum = add(y=1, x=1)
print(sum)
只要指明了函数参数的名称,那么你就可以忽略参数传递顺序。这点对于程序员而言,还是非常好的。
注意:
>>> sum = add(y=1,1) # 混合参数, 位置参数必须在关键字参数前面
File "<stdin>", line 1
SyntaxError: non-keyword arg after keyword arg
当然,Python和C++一样,也支持函数参数默认值。下面的例子展示了Python的强大之处。
def add(x, y=0):
return x + y
print(add(x=1, y=2))
print(add(x='A', y='B'))
print(add(x=123))
由于数据类型是动态的,并且字符串和数字类型都内置了加法操作,所以add函数成为了通用函数。给y设置的默认值,默认值是数字,不是字符串,所以,使用函数参数默认值的时候,只支持add数字。
注意:默认值参数只能在非默认值参数之后进行声明。
Python也支持变参,只需要在参数前加上*号即可。这样你就可以传递任意个数的参数了。
# 变参
def fun(*args): # 参数前加上*,即可成为变参函数。python会创建一个元组来接受任意参数。
for arg in args:
print(arg)
fun("123", "ABC", {"name": "Nicholas Zhao Si"})
fun("123")
fun(3.1415926)
fun() #这也是可以的
程序执行结果如下所示:
如果某些参数是必须传递的,那么建议这些参数直接写出来,不要放在可变参数内。
注意:可变参数必须放在不可变参数之后,否则可变参数之后的参数接受不到值。
>>> def func(*arg, a, b): # 可变参数放在不可变参数之前
... print(arg,a,b)
...
>>> func('1',2,3) # 函数调用的时候会发生错误
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: func() missing 2 required keyword-only arguments: 'a' and 'b'
>>>
python只拥有运行时,所以定义函数的时候,不会报错,只有当你调用这个定义的不合法的函数的时候才会报错。
C语言有结构体的形式,python没有。python的函数参数为了解决这个问题,使用关键字参数。你可以将变量和值一起传递过来。然后变量和值就会变成键值对。
def fun(**kwargs):
print(kwargs)
fun(name="Nicholas Zhao Si", gender="man", age=18)
程序执行结果如下。
从这里就能看出来python的字典就相当于C语言的结构体。有了这个功能,你就能传递任意的变量给函数了,但是需要注意的是,你必须在函数里处理你传递的参数才可以。
Python函数定义的时候,参数的顺序必须按照下面的规则来书写:
位置参数 > args(可变参数) > 默认值参数 > *kwargs(关键字参数)
另外,可变参数和关键字参数还可以使用下面的方式来传递。
# 可变参数传递
def func(*args):
print(args)
lst = [1,2,3]
func(*lst)
# 关键字参数
def func(**kwargs):
print(kwargs)
dic = {'a':1,'b':2}
func(**dic)
编写函数时,能以各种方式混合使用位置实参、关键字实参和任意数量的实参。知道这些实 参类型大有裨益,因为阅读别人编写的代码时经常会见到它们。要正确地使用这些类型的实参并 知道其使用时机,需要经过一定的练习。
_________________________python3.8加入的新特性________________________________
python3.8之后函数参数中允许出现/和*号,/表示/之前的所有参数都只能以位置参数来使用,不能以关键字参数形式来使用;*号表示*之后的参数只能以关键字参数来使用,不能以位置参数来使用。例如:
def func(a, b, /, *, c, d=3):
print(a, b, c, d)
func(1, 2, 3) # 错误,a,b可以是位置参数,c必须是关键字参数
func(0, 1, 2, 3) # 错误,c, d必须是关键字参数
func(0, 1) # 错误,参数c未传递
func(0, 1, c=2) # 正确
func(0, 1, c=2, d=4) # 正确