最近遇到了函数闭包(函数嵌套)使用,但是不是很懂调用过程,参考资料以后,进行了如下总结(顺便将python基础函数相关知识进行了复习和总结)。
一、python函数定义
- 使用"def"关键字,后接函数名与括号"()",注意末尾":"
- "[]“表示可以省略,参数由”,"分隔,可以省略
- return表示返回值给调用者,可省略,表示返回None
def function_name([param1, param2...]):
function_body
[return [expression]]
二、python函数调用与参数传递
python中,包括可更改(mutable)与不可更改(immutable)对象。
string(字符串)、tuple(元组)、number(数值)都是不可更改对象,而list(列表)、dict(字典)等则是可修改的对象。
不可变类型:例如:变量赋值
a=5
后再赋值a=10
,实质为新生成一个int对象10,再让a指向它,而5被丢弃。并不是改变了a的值,其实相当于新生成了a。
可变类型:变量赋值a=[1,2,3,4]
后再赋值a[2]=5
,只是将a[2]元素值修改。
当作为参数传递时,不可变类型相当于值传递,可变类型相当于引用传递。下面简单举两个例子:
- 传递不可变类型参数示例:
def ChangeInt(a):
a = 10
b = 2
print(ChangeInt(b)) # 结果是 2
- 若想获得改变后的参数值,可以使用return返回。
def ChangeInt(a):
a = 10
return a # 将a返回给调用
b = 2
b = ChangeInt(b) # 创建新的b接受已改变的返回值
print(b) # 结果是 10
- 传递可变类型参数示例:
def ChangeList(mylist):
mylist.append(40)
print("函数内取值: ", mylist)
mylist = [10, 20, 30]
ChangeList(mylist)
print("函数外取值: ", mylist)
三、python参数
在进行函数调用时,定义函数时的参数列表中的参数包括必需参数和非必需参数(默认参数),还有关键字参数和可变长参数。
- 必需参数
必需参数顾名思义,即在函数调用时必须给出相应参数值,否则会报错。
def printme(str):
print (str)
printme() # 会报错
printme("传入了参数") # 正确调用
- 非必需参数(默认参数)
即在函数定义时,在参数列表指定相应参数值,在函数调用时,则可不必传该参数。即若未传递该参数,则使用默认值。
def printinfo(name, age=35):
print("名字: ", name)
print("年龄: ", age)
printinfo("runoob")
- 关键字参数
使用关键字参数允许函数调用时参数的顺序与声明时不一致,因为Python解释器能够用参数名匹配参数值。将上例函数调用改为:
printinfo(age=50, name="runoob")
- 不定长参数
加了星号 * 的参数会以元组(tuple)的形式导入,存放所有未命名的变量参数。
def functionname([formal_args,] *var_args_tuple ):
function_suite
return [expression]
- 例如:
def printinfo(arg1, *vartuple):
print(arg1)
for var in vartuple:
print (var)
printinfo(70, 60, 50)
- 其输出结果为:70 60 50。其中还有
**vartuple
作为参数的形式,加了两个星号**
的参数会以字典的形式导入,例如:
def printinfo( arg1, **vardict ):
print (arg1)
print (vardict)
printinfo(1, a=2,b=3)
- 其输出结果为:1 {‘a’: 2, ‘b’: 3},若后面不是以
key=value
形式传参,会报错。
四、匿名函数
python使用lambda
来创建匿名函数。
需要注意的是,lambda
函数拥有自己的命名空间,且不能访问自己参数列表之外或全局命名空间里的参数。其语法格式为:
lambda [arg1 [,arg2,.....argn]]:expression
示例如下:
sum = lambda arg1, arg2: arg1 + arg2
print("相加后的值为 : ", sum(10, 20))
print((lambda arg1, arg2: arg1 + arg2)(10,20))
五、Global与nonlocal关键字
当内部作用域修改外部作用域变量时,需要使用该关键字。
1.global:示例如下所示,注释掉global关键字声明后,输出结果为“2 1”,因为fun()
中num
拥有局部作用域。当取消注释后,输出结果为“2 2”,因为该关键字使得num
有了全局作用域。
num = 1
def fun():
#global num # global 关键字声明
num = 2
print(num)
fun()
print(num)
注意:当对num进行修改时,不加global会报错,或者可将变量进行参数传递。
2. nonlocal:若修改嵌套作用域(enclosing 作用域,外层非全局作用域)中的变量则需要nonlocal关键字。
def outer():
num = 10
def inner():
nonlocal num # nonlocal关键字声明
num = 100
print(num)
inner()
print(num)
outer()
上面的例子输出"100 100",若注释掉nonlocal,输出"100 10"。将其改为global,和不加结果相同,即global不起作用。
六、python函数闭包(函数嵌套)
上一节已经接触了函数嵌套,接下来进行详细介绍:
首先,进行闭包格式介绍:
def 外层函数(参数1):
def 内层函数(参数2):
print("内层函数参数", 参数1)
print("外层函数参数", 参数2)
return 内层函数
内层函数的引用 = 外层函数("传入参数")
内层函数的引用(参数2)
注意:调用外层函数返回的是内层函数的引用。举例如下:
def func(a, b):
print("外层函数调用")
def line(x):
print("内层函数调用:a=%d\tx=%d" % (a, x))
return a * x - b
return line
line = func(2, 3)
print(line(5))
参考文档: