浅谈闭包函数
1.函数对象
函数对象的定义:把函数的地址当做一种函数的变量名去使用,就是函数对象。
引用函数对象通常有4种方法,分别是:
1.直接将函数名赋值给一个变量:
def func1():
print('from func1')
func2 = func1
func2()
此时func2这个变量的值便是func1这个函数的内存地址,
func2后面加个括号就等于对func1加上了括号,只是此
时调用的方式不一致,这种方法在后面的装饰器部分也又用到。
这个代码的运行结果是:
from func1
2.可以当做参数传给另外一个函数:
def func1(): print('from func1') def bar(xxx): # print(xxx) xxx() bar(func1) 如上述代码,在调用bar函数时,我们传入了另外一个函数func1, 在bar函数中,我们既输出了传入函数对象既func1的内存地址, 也对存入的函数对象进行了调用,最终结果为: <function func1 at 0x000001DB32915598> from func1
3.可以作为某个特定函数的返回值:
def fn1():
print('from func')
def bak():
return fn1
f = bak()
f()
4.可以当作容器类型的元素:在选择功能的时候可以使用这种方式,技能方便修改,也能减少代码量。
# 定义方法进行四则运算 # 定义加法功能 def add(a,b): return a+b #定义加法功能 def low(a,b): return a-b # 定义乘法功能 def jump(a,b): return a*b # 定义除法功能 def full(a,b): return a/b # 定义取余功能 def mod(a,b): return a%b # 定义四则运算功能法则 def computed(fn,n1,n2): res =fn(n1,n2) return res # 定义容器,来封装功能 cmd_dic ={ 'add':add, 'low':low, 'jump':jump, 'full':full, 'mod':mod } # 根据指令获得计算方法 def get_cp_fn(cmd): if cmd in cmd_dict: return cmd_dict[cmd] return add # 输入有误采用默认方法 while True: cmd = input('cmd:>>>>>>') if cmd not in cmd_dic: break cp_fn = get_cp_fn[cmd] res = computed(cp_fn,100,20) print(res) # 得到的运算结果为:======================== 120 80 2000 5.0 0 =====================================
2.函数的嵌套
1.函数的嵌套分为两种:嵌套定义和嵌套调用。
2.函数的嵌套调用:在函数中调用了其他的函数。
# 求两个数的最大值
def max2(a,b):
if a > b:
return a
return b
# 求三个数的最大值
def max3(a,b,c):
res = max2(a,b)
return max2(res,c)
3.函数的嵌套定义:在函数内定义了其他的函数
from math import pi
def circle(radius,mode=0):
def perimiter(radius):
return 2 * pi * radius
def area(radius):
return pi * (radius ** 2)
if mode == 0:
return perimiter(radius)
elif mode == 1:
return area(radius)
我们将求圆的周长与圆的面积的函数定义在了一个大
函数circle中,只需要选择在circle函数中传入的参数
我们就可以选择我们需要调用的函数。
3.名称空间
定义:存放名字与内存地址绑定关系的地方
名称空间分为三类:
1.内置名称空间:存储解释器自带的一些名称与值的对应关系
(python解释器启动时创建 所有代码全部执行完毕 关闭解释器时 销毁)
2.全局名称空间:只要你的名字的定义是顶着最左边写的就在全局空间(如果if顶级,那么if中的变 量名也属于全局名称空间)(执行py文件创建全局名称空间 关闭解释器时 销毁)
3.局部名称空间:只要是函数内的名称就是局部的
(调用函数时创建 函数执行完毕就销毁)
名称空间的加载顺序:内置的 -> 全局的 -> 局部的(LEGB规则)
名称的查找顺序:从当前位置往外一层一层的查找
如果当前处于局部名称空间:当前位置所在的局部----->全局------->内置
如果当前处于全局名称空间:全局------->内置
4.作用域
定义:域指的是区域,范围的的意思.。作用域就是名称空间的范围
作用域的分类:1.全局作用域 2.局部作用域
1.全局作用域:包含内置与全局名称空间的名字 特点:全局存活,全局有效
2.局部作用域:包含局部名称空间的名字 特点:临时存活,局部有效
特别注意:作用域的关系在函数的定义阶段就已经存在固定死了,与调用位置无关!!!
def f1():
print(xxx)
xxx=111
def f2():
xxx=222
f1()
f2()
调用函数f2时,这个代码的运行结果为111,因为在函数定义时,
f1中有一个print(xxx),但是在f1函数这个局部作用域中并没
有xxx这个变量,所以它会向外部(全局作用域)中区寻找,返现
xxx=111,所以在调用f2时,输出结果会是111,因为在函数定义的时候已经固定死了
5.闭包
定义:闭函数:该函数一定是定义在函数内的函数
包函数:该内部函数包含对外层函数作用域名字的引用
闭包函数模板:
def outer():
x = 10
def inner():
print(x)
return inner
闭包函数也可以为函数体传值:
def outter(x):
def inner():
print(x)
return inner
global是在局部变量中声明变量是全局变量,并且可以在局部变量中修改全局变量的值;而nonlocal在局部变量中声明变量是外层函数变量(永远都不会找到全局变量中)