Python函数变量调用顺序及闭包

这里写图片描述

全局变量v.s.局部变量

类似C++里的变量,对变量赋值前需要先声明变量,即要为变量在内存开辟空间。注意下面的全局变量和局部变量定义:
这里写图片描述

Python解释器的LEGB查找变量顺序
passline = 60

def func(val):
    #定义函数func时,引入local函数作用域;调用函数func时,val就是本地变量    
    if val >= passline:
        #在函数func内部没有定义passline,Python解释器去全局变量找这个变量的定义
        print('pass')
    else:
        print('failed')

func(89)
#Output:pass
passline = 60   #全局

def func(val):
    passline = 90   
    #局部,函数内部local
    #Python解释器首先从local开始查找passline,如果没有再去上一层查找
    if val >= passline:
        print('pass')
    else:
        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')
    else:
        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)函数返回值

passline = 60   #全局
def func(val):
    print('%x' % id(val))   #以16进制打印变量val的id

    if val >= passline:
        print('pass')
    else:
        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:
        return 0
    for val in arg:
        if not isinstance(val,int):
            return 0
    ##############################    
    return sum(arg)

def my_average(*arg):
    ##############################
    if len(arg)==0:
        return 0
    for val in arg:
        if not isinstance(val,int):
            return 0
    ##############################    
    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:
            return 0
        for val in arg:
            if not isinstance(val,int):
                return 0
        ##############################
        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:
            return 0
        for val in arg:
            if not isinstance(val,int):
                return 0
        ##############################
        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:
            return 0
        for val in arg:
            if not isinstance(val,int):
                return 0
        ############################## 
        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进行计算
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值