Python函数变量调⽤顺序及闭包
全局变量v.s.局部变量
类似C++⾥的变量,对变量赋值前需要先声明变量,即要为变量在内存开辟空间。注意下⾯的全局变量和局部变量定义:
Python解释器的LEGB查找变量顺序
passline = 60
def func(val):
#定义函数func时,引⼊local函数作⽤域;调⽤函数func时,val就是本地变量
if val >= passline:
#在函数func内部没有定义passline,Python解释器去全局变量找这个变量的定义
print('pass')
el:
print('failed')
func(89)
#Output:pass
def func(val):
passline = 90
#局部,函数内部local
#Python解释器⾸先从local开始查找passline,如果没有再去上⼀层查找
if val >= passline:
print('pass')
el:
print('failed')
func(89)
#Output:Failed
def MAX(v1,v2):
return max(v1,v2) #max存在于buildin⾥,Python解释器⾃动从函数MAX向上查找
MAX(90,100)
#Output:100
passline = 60#全局
def func(val):
passline = 90
if val >= passline:
print('pass')
el:
print('failed')
def in_func():
print(val)
#val值在in_func函数local作⽤域找不到定义,往上层找:func函数引⼊val变量,闭包
in_func() #对func的内嵌函数进⾏调⽤
func(89)
#Output:failed
# 89
钦州地区闭包closure
内部函数对enclosing作⽤域的变量的使⽤,将该变量放到内部函数的__closure__属性中,内部函数可以直接使⽤该属性,从⽽实现封装和代码复⽤
函数实质与属性
(1)函数是⼀个对象,在内存⾥会有⼀个存储的空间(2)函数每执⾏完⼀次,其内部变量都会被Python解释器回收,return的变量不会回收(3)函数属性(4)函数返回值
def func(val):
print('%x' % id(val)) #以16进制打印变量val的id
if val >= passline:
print('pass')
el:地球的主人
print('failed')
def in_func():#向in_func的函数属性__closure__添加元组(val,)
print(val)
in_func()
你幸福我才快乐
return in_func #in_func是func()函数内部⽣成的⼀个函数对象
f=func(89)
print(' ')
f() #func函数执⾏完,return的in_func函数对象还在内存⾥,val被释放掉
print(' ')
print(f.__closure__) #函数的closure属性
#Output:10b3e4060
# pass
# 89
#
# 89
#
# (<cell at 0x10d8f6d98: int object at 0x10b3e4060>,)
#对⽐val的id和f.__closure__可见:
#闭包in_func"引⽤enclosing作⽤域的变量"后,会"将该变量添加到闭包in_func属性⾥" #再次查找该变量时,是去引⽤该变量的闭包的属性⾥查找
清纯美女照片def my_sum(*arg):
>>>>>>重复代码if len(arg)==0:
return0
for val in arg:
if not isinstance(val,int):
豫园
return0
>>>>>>return sum(arg)
def my_average(*arg):
>>>>>>if len(arg)==0:
return0
for val in arg:
if not isinstance(val,int):
return0
>>>>>>return sum(arg)/len(arg)
print(my_sum(1,2,3,4,5))
print(my_sum(1,2,3,4,5,'6'))
print(my_average(1,2,3,4,5))
print(my_average())
#Output:15
# 0
# 3.0
# 0
###重新设计my_sum和my_average的结构:
#以上两个函数,中间判断条件代码重复古代的字
#可以将“中间重复判断条件代码”抽出来,以闭包的形式定义函数,调整结构
#【0】抽剪结构:
def my_sum(*arg):
return sum(arg)
def my_average(*arg):
return sum(arg)/len(arg)
#【1】设计雏形:
def dec(func):#dec的参数是⼀个函数
def in_dec(*arg):#in_dec处理上⾯的判断参数类型的代码块部分
神奇魔镜pass
return in_dec
#【2】闭包设计:
def dec(func):#func是传递的⼀个函数,调⽤它的时候想让它做什么就写成什么def in_dec(*arg):
>>>>>>if len(arg)==0:
return0
for val in arg:
if not isinstance(val,int):
return0
>>>>>>return func(*arg) #希望func处理*arg
晴天尤克里里return in_dec
my_sum=dec(my_sum) #对函数值my_sum赋值为dec(my_sum)
#dec(my_sum)调⽤dec函数,将my_sum函数作为参数传⼊
#【my_sum=in_dec(*arg)】
#在闭包in_dec中使⽤了my_sum:
#my_sum被放⼊in_dec的__closure__属性⾥,in_dec函数内部直接对my_sum函数进⾏引⽤
#【3】确定in_dec(*arg)的参数调⽤:
def dec(func):
def in_dec(*arg):
print('in_dec arg = :',arg) #测试arg参数调⽤
>>>>>>if len(arg)==0:
return0
for val in arg:
if not isinstance(val,int):
return0
>>>>>>return func(*arg)
return in_dec
# my_sum=dec(my_sum)
# print(my_sum(1,2,3,4,5))
# print(my_sum(1,2,3,4,5,'6'))
#【4】确定调⽤顺序:
def my_sum(*arg):
print('in my_sum')
return sum(arg)
def dec(func):
def in_dec(*arg):
print('in_dec arg = :',arg) #测试arg参数调⽤
>>>>>>if len(arg)==0:
return0
for val in arg:
if not isinstance(val,int):
return0
>>>>>>return func(*arg)
return in_dec
my_sum=dec(my_sum)
#调⽤dec,返回in_dec函数;在in_dec闭包⾥引⽤了传递的my_sum函数
#⽤dec(my_sum)的返回值给my_sum赋值,my_sum指向in_dec
#所以,调⽤my_sum时,⾸先调⽤in_dec;然后调⽤传递给func的参数my_sum
print(my_sum(1,2,3,4,5))
print(my_sum(1,2,3,4,5,'6'))
#Output:in_dec arg = : (1, 2, 3, 4, 5)
# in my_sum
# 15
# in_dec arg = : (1, 2, 3, 4, 5, '6')
# 0
#调⽤顺序:step1,调⽤in_dec函数;step2,调⽤func参数对应的my_sum函数;
#即所有参数先交给in_dec处理,再由my_sum进⾏计算