函数也是对象
别忘了,Python中一切且对象
函数应该理解为“函数对象”,可通过id()
BIF查看其对象标识符
使用函数名+小括号,可以调用函数
使用函数名(没有小括号),可以得到函数对象,并像处理普通变量一样处理它
向函数传递函数:函数可以作为参数
- 函数可以接收另一个函数(准确的说,是函数对象)作为参数
- 函数可以调用传入的函数对象
使用函数名+小括号,可以调用传入的函数对象
例如,定义一个函数,它接收两个参数:一个函数对象和一个值(可以是任意对象)
函数内部调用了所传入的函数
def apply(func: object,value: object) -> object:
return func(value)
=================== RESTART: C:/Users/13272/apply.py ===================
>>> apply(print,'Hello')#调用传入的print函数
Hello
>>> apply(type,1)#调用传入的type函数
<class 'int'>
>>> apply(type,apply)#调用传入的type函数
<class 'function'>
从函数返回函数:函数可以作为返回值
- 函数内部可以定义另一个嵌套函数
(嵌套的函数只在外围函数的作用域中可见) - 可以将嵌套函数作为函数返回值(返回的是一个函数对象)
def outer():
def inner():
print('This is inner.')
return inner
================= RESTART: C:/Users/13272/Desktop/example.py =================
>>> i = outer()
>>> i()
This is inner.
从outer()返回一个嵌套函数inner,并将返回值(函数对象)赋给i
此时i的类型就是函数,i相当于inner函数的一个别名
处理任意多的参数
*
代表“(将可展开的列表)展开为多项”,与列表搭配使用
**
代表“(将可展开的字典)展开为多个键值对”,与字典搭配使用
*args
和**kwargs
都可以“直接使用”,因为列表或关键字集合可以作为一个(可展开的)参数传入函数;使用(*args
,**kwargs
)作为函数签名时,所创建的函数可以接收任意数量和类型的参数。
对于位置赋值:接收一个任意的列表,作为参数
位置赋值:根据
def
语句中的参数的顺序来为参数赋值
在函数的def
行使用*args
,指示函数唯一的参数是一个列表args
(大小任意),在调用时,参数的书写形式为[此列表展开后的多个项]
(尽管理论上讲*args
是一个元组)
*
意为“任意数字”,可以把*
理解为“(将可展开的列表)展开为多项”- 按惯例,参数名使用
args
,args
在函数内部相当于一个参数的列表(实际上是元组)
def myfunc(*args):
for a in args:
print(a,end=' ')
================= RESTART: C:/Users/13272/Desktop/example.py =================
>>> myfunc()
>>> myfunc()
>>> myfunc(1,2,3)
1 2 3
>>> myfunc('H','i')
H i
还可以直接使用*
调用函数时,用*
和列表搭配,表示要把列表拆分为多项独立的参数,再传入函数
- 如果向函数传入一个列表,这个列表(包含多个值)会被处理为一项
- 调用函数时,在列表名前面加
*
前缀,指示解释器展开列表(使列表的每一项作为一个单独的参数)
>>> mylist = [1,2,3,4,5]
>>> myfunc(mylist)
[1, 2, 3, 4, 5]
>>> myfunc(*mylist)
1 2 3 4 5
对于关键字赋值:接收一个任意的字典,作为参数
关键字赋值:按参数名来指定参数的值
在函数的def
行使用**kwargs
,指示函数唯一的参数是一个字典(大小任意),调用时参数的书写形式为[此字典展开后的多个键值对]
- 可以把
**
理解为“(将可展开的字典)展开为多个键值对” - 按惯例,参数名使用
kwargs
(keyword关键字参数),kwargs
在函数内部相当于一个关键字参数的字典
def myfunc2(**kwargs):
for k,v in kwargs.items():
print(k,v,sep='->',end=' ')
================= RESTART: C:/Users/13272/Desktop/example.py =================
>>> myfunc2(a=1,b=2)
a->1 b->2
>>> myfunc2(a=10,b=20,c=30,d=40)
d->40 a->10 b->20 c->30
还可以直接使用**
调用函数时,用**
和字典搭配,表示要字典拆分为多个独立的关键字参数
- 如果向函数传入一个字典,这个字典会被处理为一项参数
- 调用函数时,在字典名前面加
**
前缀,指示解释器展开为关键字参数(使字典的每一个键值对作为一个单独的关键字参数)
接收任意数量的位置参数/关键字参数
结合使用*args,**kwargs
作为参数,并分情况处理传入的位置参数/关键字参数
def myfunc3(*args,**kwargs):
if args:
for a in args:
print(a,end=' ')
elif kwargs:
for k,v in kwargs.items():
print(k,v,sep='->',end=' ')
================= RESTART: C:/Users/13272/Desktop/example.py =================
>>> myfunc3(1,2,3)
1 2 3
>>> myfunc3(a=1,b=2)
a->1 b->2