函数是一组语句的集合,用来执行特定操作,可以有参数决定内部逻辑,也可以再执行完毕后返回一个值。函数可以将复杂的操作封装在一起,避免直接接触内部的业务逻辑,只用关注函数的功能。
函数的定义
由于解释器的性质,函数必须定义在使用之前,以保证在调用时函数已经被解释器解析。
定义函数使用 def
关键字。
1 | def function_name(parameters): |
参数
参数在调用函数时从函数外部传入,供函数内部使用。外部传入的值称为实际参数(实参),函数内部使用的参数为形式参数(形参)。在向函数传递参数时,传入的实际上是参数的拷贝,而不是参数本身。在函数内对形参的修改不会影响实参。
函数在定义完成后可以像一个普通变量一样被使用,或者传递给另一个函数。
1 | def foo(): |
调用函数
函数在完成定义后就可以调用了。
1 | def foo(a,b,c,d): |
函数的传参
指定参数
在传参时,可以直接给参数名赋值,指定要传入的形参。
1 | def foo3(a,b,c,d): |
指定形参必须出现在调用语句的最后,其后不允许出现普通传参。
1 | def foo3(a,b,c,d): |
在函数内部修改实参
Python
中的类型分为可变类型和不可变类型。不可变类型的变量储存的是变量本身;可变类型的变量存储的则是对对象的引用,就像一个人自己和这个人的名片。在传参时,不可变类型的实参会被拷贝一份然后赋值给形参,形参获得的是一个新值;可变类型的实参同样会被复制,但是复制的是引用(就像名片无论怎么复制指向的都是同一个人),对修改的修改会作用到实参上。
1 | def foo(a:int,b:list): |
参数的默认值
正常情况下,当给函数传入的参数少于参数列表中参数数量时,解释器会报错。由于 Python
不允许函数重载,于是提供了参数默认值,可以在函数定义允许的情况下不传入有默认值的参数,此时未传入实参的形参的值就是默认值。
定义默认值很简单,直接在参数列表通过 =
对参数赋值即可。
1 | def foo2(a,b=2): |
Python
函数有默认值的参数必须放在参数列表的最后。
1 | def foo(a,b,c=1,d=2)#正确 |
参数列表
有时候函数可能会面临传入未知数目参数的情况,可能是几个也可能是几十个。为了应对这种情况,Python
提供了两种特殊的参数标识符: 参数列表 *
和关键字参数列表 **
,用于标记参数,并将传入的参数打包存入有这些标记的参数中。
*args
1 | def foo(a,*args):#args即为参数列表,名称可以自定义,会将收到的参数打包为元组 |
在
*args
参数列表后出现的普通参数必须通过指定形参来传参。
1 | def foo(a,b,c=1,*args)#正确 |
**kwargs
在指定要传入的形参时,除了可以指派给位于参数列表的形参,也可以指派给不存在的形参。
1 | def foo(a,*args,**kwargs):#kwargs即为关键字参数列表,名称可以自定义,会将收到的参数打包为字典 |
**kwargs
只允许出现在参数列表的最后,与*args
同时使用时其之间的参数只能通过指定的方式传参。
1 | def foo(a,*args,b=1,c,**kwargs): |
参数拆包
*
和 **
标记除了可以在参数列表标记特殊参数,也可以用于在传参时拆包集合类型。*
会展开集合类型;**
会将字典中键值对的 值
传入 键
对应的形参,即 key = value
。
1 | args = [1,2,3,4] |
函数的返回值
函数可以通过 return
返回一个返回值。
1 | def add(a,b): |
使用 return
返回值后,函数即结束执行,后续所有语句都会被忽略。如果只想结束函数的执行,可以直接 return
而不返回值,此时返回值为 None
。
函数存在返回值时,整个被调用函数为右值表达式。
匿名函数
除了使用 def
关键字定义的有自己名称的函数,还有另一种没有名称的函数,只有参数列表、函数体和返回值,称为匿名函数,又称Lambda表达式。
匿名函数的定义
定义匿名函数使用 lambda
关键字。
1 | lambda paramters:expr |
使用匿名函数
匿名函数可以像普通函数一样使用,也可以赋值给其他变量然后使用。
1 | foo = lambda x,y,z: x + y + x |
通常匿名函数不是直接拿来使用的,而是其他函数需要传入一个函数作为参数时,传入匿名函数而不用大费周章的使用 def
定义函数再传入。
装饰器
装饰器如其名,用于给函数外挂一些东西,从而修改函数的行为。
装饰器的定义
装饰器是一类特殊的函数,接受一个函数作为参数并返回一个函数,传入的函数即为被包装的函数。
1 | def decorator_func(target_func):#装饰器函数 |
使用装饰器
装饰器使用在函数定义的位置,在函数定义的 def
语句的上一行,以 @
开头。
1 |
|
带参数的装饰器
装饰器可以带参数,对应的函数需要多一层。
1 | def my_decorator(x,y,z):#xyz即装饰器的参数 |
类装饰器
装饰器不仅可以是一个函数,也可以是一个类,此处将会在 类与对象 章节介绍。
写在最后
装饰器可以动态修改函数的行为,记录函数的调用信息、拦截特定的调用、限制函数访问权限等功能而不用修改函数本身,是 Python
中十分强大的一个特性。