龙空技术网

闭包函数 | Python

VT聊球 171

前言:

如今大家对“python函数闭包”大约比较关注,姐妹们都需要剖析一些“python函数闭包”的相关内容。那么小编在网络上搜集了一些关于“python函数闭包””的相关知识,希望咱们能喜欢,小伙伴们一起来学习一下吧!

一、函数嵌套

函数嵌套调用

函数嵌套调用指的是在函数内部又调用了其他的函数。

#  求三个数的最大值def max2(x, y):    if x > y:        return x    else:        return ydef max3(x, y, z):    res1 = max2(x, y)    res2 = max2(res1, z)    return res2print(max3(11, 199, 2))

函数嵌套定义

函数的嵌套定义指的是在函数内又定义了其他函数

# 示例1def func1():    print('from func1')    def func2():        print('from func2')    print(func2)    func2()func1()# print(func2)# 示例2# 函数在定义阶段不执行函数体内的代码def f1():    print('f1')    def f2():        print('f2')        def f3():            print('f3')        f3()    f2()f1()
二、名称空间

名称空间说明

名称空间从字面意思理解是存放名字的地方,最开始我们在讲解变量的时候知道:定义一个变量就是开辟一块内存空间,这个内存空间存放的是变量的值,除了变量值之外,还有变量名,变量名与变量值的绑定关系这个数据要在内存中存储。变量名是名字,函数名也是名字,名称空间就是存放名字与值的绑定关系的地方。

名称空间的分类

名称空间分为三类:

内置名称空间:存放Python解释器自带的名字,在解释器启动时就生效,解释器关闭则失效。全局名称空间:文件级别的名字,在执行文件的时候生效,在文件结束或者在文件执行期间被删除则失效。有些全局名称空间可能一眼看上去不像是全局名称空间,我们只需要记住,只要不是内置名称空间和局部名称空间,那么就是全局名称空间。局部名称空间:存放函数内定义的名字(函数的参数以及函数内的名字都存放于局部名称空间),在函数调用时临时生效,函数结束则失效。

# 内置print(print)print(len)# 以下4个都是全局x = 1  # 全局def func():  # func是全局名称空间    name = 'Albert'  # name是局部名称空间# del func  # 我们不需要自己删除if 10 > 3:    y = 2  # 全局while True:    z = 5  # 全局    break# 局部def func1(x):  # 实参1传给形参x就相当于在函数内被定义 x=1,故x为局部    # x = 1    y = 2  # 局部func1(1)

内置名称空间与全局名称空间的结束的生命周期基本上是一致的,程序执行结束或者文件关闭(手动强制关闭写python代码的这个文件),内置或全局名称空间生命周期结束。局部名称空间生命周期是从函数调用开始到函数结束,即函数生命周期终止。

加载顺序:内置名称空间->全局名称空间->局部名称空间

查找名字:局部名称空间->全局名称空间->内置名称空间

# 加载顺序很好理解,查找顺序是以当前位置为起始点len = 0  # 我们是为了测试,自己写代码千万不能覆盖内置名称空间def f1():    # len = 1    def f2():        # len = 2        print(len)    # len = 3    f2()f1()
三、作用域

全局作用域

全局作用域包含的是内置名称空间与全局名称空间的名字,它的特点是:

在任何位置都能够访问的到该范围内的名字会伴随程序整个生命周期

如果在局部使用全局作用域的变量,是没有问题的,但是如果是在局部修改全局作用域的变量则不能直接修改,而要使用global关键字才可以修改。

global_count = 0def global_check():    print(global_count)  # 直接使用全局变量def global_modify():    global global_count  # 修改前需要先使用global    global_count += 1    print(global_count)global_check()global_modify()

局部作用域

局部作用域包含的是局部名称空间的名字,它的特点是:

只能在函数内使用调用函数时生效,调用结束失效

如果在局部使用的是嵌套在函数内部的局部变量,同理,可以直接使用,而修改需要使用nonlocal关键字。

def make_counter():    count = 0    def check_counter():        print(count)    check_counter()    def modify_counter():        nonlocal count        count += 1        print(count)    modify_counter()make_counter()
四、函数对象

函数对象说明

函数在Python中是第一类对象,这句话可以通俗理解为函数也是一个对象,就像是int,字符串,列表和字典一样都是对象,等讲到了面向对象我们就会对这个概念有了进一步理解,现在就可以暂时理解为函数对象可以像int或者字符串一样使用。

# 1 函数可以被引用# int示例x = 1y = x# 函数示例def bar():    print('from bar')f = barf()# 2 可以当作参数传入# int示例x = 1def func(a):    print(a)func(x)# 函数示例def bar():    print('from bar')def wrapper(func):    func()wrapper(bar)# 3 可以当作函数的返回值# int示例x = 1def foo():    return xres = foo()print(res)# 函数示例def bar():    print('from bar')def foo(func):    return funcf = foo(bar)f()# 4 可以当作容器类型的元素# int示例z = 1l = [z, ]print(l)# 函数示例def get():    print('from get')def put():    print('from put')l1 = [get, put]l1[0]()

函数对象应用(重点)

利用这一特性,可以优雅的取代原来的if多分支(elif这种多分支是我们写代码要尽可能避免的)。

def auth():    print('登陆。。。。。')def register():    print('注册。。。。。')def check():    print('查看。。。。')def transfer():    print('转账。。。。')def pay():    print('支付。。。。')func_dict = {    '1': auth,    '2': register,    '3': check,    '4': transfer,    '5': pay}def interactive():    while True:        print("""        1 登录        2 注册        3 查看        4 转账        5 支付        """)        choice = input('>>: ').strip()        if choice in func_dict:            func_dict[choice]()        else:            print('非法操作')interactive()  # 是不是比多个if...elif...简洁明了多了?
五、闭包函数

闭包函数说明

闭包函数就是定义在函数内部的函数,也就是函数的嵌套定义,根据字面意思理解,闭包函数有两个关键字闭和包分别是的封闭和包裹。需要注意的重点是:闭包函数的作用域关系在函数定义阶段就固定死了,与调用位置无关。

def outer():    x = 1    def inner():  # 在outer函数内部再定一个函数        # x = 2          print('from inner', x)    return inner  # outer函数返回inner函数对象f = outer()  # 现在的f是一个全局变量,同时是inner函数对象print(f)x = 3  # 这个x = 3并不能改变inner函数外层的xf()def foo():    x = 4  # 这个x = 4 同样也不能改变    f()  # 全局作用域在任意位置都可以调用foo()

闭包函数可以用外层函数来调用内部的函数,打破了函数的层级限制,与此同时该函数包含对外部函数作用域中名字的引用。

def outer():    name = 'Albert'    def inner():        print('my name is %s' % name)    return innerf = outer()f()

为函数体传值的两种方式

以参数的形式的传入

# 模块的导入后面章节会讲解,requests模块就是模拟浏览器向目标站点发请求import requestsdef get(url):    response = requests.get(url)  # get方法获取请求返回对象    print(response)    if response.status_code == 200:  # 200是一个状态码,代表请求成功        print(response.text)  # text方法是获取返回对象的内容get(';)

以闭包函数的形式

闭包函数就是在函数外层再包裹一层作用域,由于这个作用域在外层函数内部,所以只作用在内层函数上。

import requestsdef outer(url):  # 给外层函数传参就相当于 url=';    # url=';  # 这个作用域就是作用在get函数上的    def get():        response = requests.get(url)        if response.status_code == 200:            print(response.text)    return getbaidu = outer(';)python = outer(';)baidu()print('=================================>')python()

简化与总结闭包函数用法

def outer(x):    def foo():  # foo虽然没有直接传参,但是outer函数的作用域赋予了x动态变化        print(x)    return foof_10 = outer(10)f_10()f_100 = outer(100)f_100()

标签: #python函数闭包