函数的作用域和匿名函数、闭包、回调
一、匿名函数:
1、filter函数,可以过滤出列表中大于3的数据,但是使用都需要提前定义一个函数,有没有更加简便的方式呢?
def f(o): # 过滤器
if o>3:
print(o)
list(filter(f,[3,1,5,9,7,10]))
运行截图:

2、匿名函数(lambda后面是空格)
# lambda 参数 : 表达式
print(list(filter(lambda o:o>3,[3,1,5,9,7,10]))) # 不需要使用函数就能够完成
运行截图:

二、函数作用域
思考:
在函数里面也有可以定义变量,那函数里面的变量名如果和函数外面的变量名重名,会相互影响吗?
1、 函数里面可以访问外面的变量,但不可以修改
a=1 # 先声明变量 a # 把外面的当做爸爸
def f(): # 儿子
print(a)
f()
运行截图:

2、外部不能访问函数内部变量,函数里面和函数外部变量名可以相同,互相不影响
a=1 # 爸爸
def f():
a=123
print(a)
f() # 123 # 函数里面有的这个变量就自己,外面的不可以访问函数里面的变量
print(a) # 打印的是函数外面的a===函数里面和外面的相互不受影响
运行截图:

3、函数里面不能修改函数外部变量
a = 1 # 爸爸
def f(): # 儿子
a = a + 1 # 不可以改变爸爸的变量
print(a)
f() # 3 函数里面只可以访问不可以修改
运行截图:

4. global(全局变量) 和 nonlocal(局部变量)

a = 1 # 爸爸 ===称为全局变量
def f(): # 儿子 ===局部变量
global a # 声明外面变量===外面的变量就发生了变化
a = a + 1 # global 声明后可以改变爸爸的变量
print(a)
print(id(a))
f()
print(a)
print(id(a)) # global声明后里外输出的值均为2,id也是一样的
运行截图:

如果不声明全局变量,那么函数里面不能修改函数外部变量

以上总结:局部的可以拿全局变量,全局不可以拿局部的。
5、 函数在什么时候执行?
a=1
def f():
a=2
# 函数里面可以放任何东西
def f2():
a=3
print(123)
#
f() # 所以这样写f2函数不会执行
print(a)
运行截图:

调用f2() 才可以执行对应代码块 == (函数名+括号)
a=1
def f():
a=2
# 函数里面可以放任何东西
def f2():
a=3
print(123)
f2()
f() # 函数在什么时候执行?
# f2() 不可以这样写
print(a)
运行截图:

如果注释这里的变量值a就向上一级要值,儿子向=====》》》爸爸要值
a=1
def f():
a=2
print(a) # 2
# 函数里面可以放任何东西
def f2():
# a=3 # 如果注释这里的变量值a就向上一级要值 儿子=====》》》爸爸
print(a)
print(123)
f2()
f() # 函数在什么时候执行?(函数名+括号)
print(a)
运行截图:

如果爸爸没有就向爷爷咨询要值
a=1
def f():
# a=2
# print(a) # 2 # 如果爸爸没有就向爷爷咨询要值 一层一层的取值
# 函数里面可以放任何东西
def f2():
# a=3 # 如果注释这里的变量值a就向上一级要值 儿子==》》爸爸 如果爸爸没有就向爷爷咨询要值
print(a)
print(123)
f2()
f() # 函数在什么时候执行?(函数名+括号) 所以这样写f2函数不会执行
print(a)
运行截图:

global a 全局变量的作用,改变外部函数参数值大小
a=1
def f():
global a
a=a+5
print(a) # 6
# 函数里面可以放任何东西
def f2():
# a=3 #
print(a) # 6
print(123)
f2()
f() # 函数在什么时候执行?(函数名+括号)
print(a) # 6
运行截图:

# 注释global a后:
a=1
def f():
# global a
a=2
print(a)
# 函数里面可以放任何东西
def f2():
# a=3
print(a)
print(123)
f2()
f() # 函数在什么时候执行?(函数名+括号)
print(a)
运行截图:

nonlocal: 在函数嵌套函数的情况下,同样也有函数作用域的问题,但是python3中提供了方便,只需要使用nonlocal就可以在里层函数内部修改外部函数变量
a=1
def f():
# global a
a=2
print(a)
# 函数里面可以放任何东西
def f2():
nonlocal a # 声明局部(改变的是上级局部变量)
# a=3
a=a+5
# print(a)
print(123)
f2()
print(a)
f() # 函数在什么时候执行?
print(a)
运行截图:

global a # 声明全局变量
a=1
def f():
# global a
a=2
print(a)
# 函数里面可以放任何东西
def f2():
global a # 声明全局变量
# a=3
a=a+5
print(a)
print(123)
f2()
f() # 函数在什么时候执行?(函数名+括号) 所以这样写f2函数不会执行
print(a)
运行截图:

总结:

三、闭包
思考:函数里面可以再定义函数,那函数里面定义的函数可以在外面调用吗?如果可以的话,要怎么做呢?
'''
闭包是函数里面嵌套函数,外层函数返回里层函数,这种情况称之为闭包
闭包是概念,不是某种函数类型,和递归的概念类似,就是种特殊的函数调用
闭包可以得到外层函数的局部变量,是函数内部和函数外部沟通的桥梁
'''
例1:
def f():
print('这里是f函数')
def f2():
print('这里是f2函数')
return f2 # 返回的是f2 函数
# return 123 # 返回的是123
a=f() # a====f2函数 (函数名+括号) 代表调用
a() # 调用f2 闭包:外层函数返回内层函数
print(a) # 返回的是123
# print(f)
运行截图:

例2:
def f():
print('这里是f函数')
def f2():
print('这里是f2函数')
# return f2 # 返回的是f2 函数
return 123 # 返回的是123
a=f() # a====f2函数 (函数名+括号) 代表调用
# a() # 调用f2 闭包:外层函数返回内层函数
print(a) # 返回的是123
运行截图:

例3:
def f():
print('这里是f函数')
def f2():
b=1
print('这里是f2函数')
return b+2
return f2 # 对于f2函数来说哪里调用的就返回哪里
a=f() # a====f2函数 (函数名+括号) 代表调用 并传给a,由a接受
l=a() # 代表调用f2 闭包:外层函数返回内层函数
print(l)
运行截图:

例4:
def fun(a):
print(a)
def fun1():
print(a,11)
return fun1 # 调用不行执
a = fun(3)
a() # 相当于 fun(3)() 调用fun1
运行截图:
四、递归和回调函数
思考:
1、函数里面可以自身调用自身吗?
递归中可以函数自身调用自身,但是使用时类似于条件循环一样,要有递归的终止条件
递归应用:
使用递归时,常常可以让代码更加简洁 递归会占用比较多的内存,当递归次数比较多时,性能就会降低, 因此不建议多使用递归
例1:
递归:自己调用自己称为递归
def f(n):
if n==1:
return 1
return f(n-1)*n
# 5*f(4) 5*4*f(3) 5*4*3*f(2) 5*4*3*2*f(1)
a=f(5)
print(a)
运行截图:

2、 回调函数:一个函数当做是一个参数传给另一个函数--- 称为回调
自身是一个函数,只是被传入到另一个函数当中,供其调用 回调函数不一定会被调用,是否调用由被传入函数的内部逻辑决定
例1:
def f():
print('这里是f函数') # f 为回调函数
def f2(o):
print('这里是f2函数')
# o为参数
o() # ====说明在调用f函数
f2(f)
运行截图:

例2:
def f(a):
# print(a)
#
# def f2(o):
# print('这里是f2函数')
# # o为参数
# o(15) # ====说明在调用f函数,哪里调用就在哪里传参!
#
# f2(f)
运行截图:


浙公网安备 33010602011771号