zoukankan      html  css  js  c++  java
  • 一篇文章学会 Python 中闭包与变量作用域

    1. 作用域

    Python的作用域可以分为四种:

    • L (Local) 局部作用域
    • E (Enclosing) 闭包函数外的函数中
    • G (Global) 全局作用域
    • B (Built-in) 内建作用域

    变量/函数 的查找顺序:
    L –> E –> G –>B

    意思是,在局部找不到的,便去局部外的局部作用域找(例如 闭包),再找不到的就去全局作业域里找,再找不到就去内建作业域中找。

    会影响 变量/函数 作用范围的有

    • 函数:def 或 lambda
    • 类:class
    • 关键字:global noglobal
    • 文件:*py
    • 推导式:[],{},()等,仅限Py3.x中,Py2.x会出现变量泄露。

    1、赋值在前,引用在后

    # ------同作用域内------
    name = "MING"
    print(name)
    
    # ------不同作用域内------
    name = "MING"
    def main():
        print(name)
    

    2、引用在前,赋值在后(同一作用域内)

    print(name)
    name = "MING"
    
    # UnboundLocalError: local variable 'name' referenced before assignment
    

    3、赋值在低层,引用在高层

    # L -> E -> G -> B
    # 从左到右,由低层到高层
    def main():
        name = "MING"
    
    print(name)
    # NameError: name 'name' is not defined
    

    2. 闭包

    在一个外函数中定义了一个内函数,内函数里运用了外函数的临时变量,并且外函数的返回值是内函数的引用。这样就构成了一个闭包。其实装饰函数,很多都是闭包。

    好像并不难理解,为什么初学者会觉得闭包难以理解呢?

    我解释一下,你就明白了。

    一般情况下,在我们认知当中,如果一个函数结束,函数的内部所有东西都会释放掉,还给内存,局部变量都会消失。但是闭包是一种特殊情况,如果外函数在结束的时候发现有自己的临时变量将来会在内部函数中用到,就把这个临时变量绑定给了内部函数,然后自己再结束。

    你可以看下面这段代码,就构成了闭包。在内函数里可以引用外函数的变量。

    def deco():
        name = "MING"
        def wrapper():
            print(name)
        return wrapper
    
    deco()()
    # 输出:MING
    

    3. 改变作用域

    变量的作用域,与其定义(或赋值)的位置有关,但不是绝对相关。
    因为我们可以在某种程度上去改变向上的作用范围。

    • 关键字:global
      将 局部变量 变为全局变量

    • 关键字:nonlocal
      可以在闭包函数中,引用并使用闭包外部函数的变量(非全局的噢)

    global好理解,这里只讲下nonlocal。

    先来看个例子

    def deco():
        age = 10
        def wrapper():
            age += 1
        return wrapper
    
    deco()()
    

    运行一下,会报错。

    # UnboundLocalError: local variable 'age' referenced before assignment
    

    但是这样就OK

    def deco():
        age = 10
        def wrapper():
            nonlocal age
            age += 1
        return wrapper
    
    deco()()
    # 输出:11
    

    其实,你如果不使用 +=-=等一类的操作,不加nonlocal也没有关系。这就展示了闭包的特性。

    def deco():
        age = 10
        def wrapper():
            print(age)
        return wrapper
    
    deco()()
    # 输出:10
    

    4. 变量集合

    在Python中,有两个内建函数,你可能用不到,但是需要知道

    • globals() :以dict的方式存储所有全局变量
    • locals():以dict的方式存储所有局部变量

    globals()

    def foo():
        print("I am a func")
    
    def bar():
        foo="I am a string"
        foo_dup = globals().get("foo")
        foo_dup()
    
    bar()
    # 输出
    # I am a func
    

    locals()

    other = "test"
    
    def foobar():
        name = "MING"
        gender = "male"
        for key,value in locals().items():
            print(key, "=", value)
    
    foobar()
    # 输出
    # name = MING
    # gender = male
    

    文末福利

    本人原创的 《PyCharm 中文指南》一书前段时间一经发布,就火爆了整个 Python 圈,发布仅一天的时间,下载量就突破了 1000 ,并且在当天就在 Github 上就收获了数百的 star,截至目前,下载量已经破万。

    这本书一共将近 200 页内含大量的图解制作之精良,值得每个 Python 工程师 人手一份。

    为方便你下载,我将这本书上传到 百度网盘上了,你可以自行获取。

    链接:https://pan.baidu.com/s/1-NzATHFtaTV1MQzek70iUQ

    密码:mft3

  • 相关阅读:
    域hash值破解的总结经验
    centos下安装ngnix+php+mysql服务
    方程式EQGRP_Lost_in_Translation工具之fb.py
    Bypass AV meterpreter免杀技巧
    跟我一起创建栈
    vue-cli3使用yarn run build打包找不到路径
    使用vue-cli3快速适配H5项目
    关于判断是安卓还是ios环境跳转下载页
    跟我一起学习webpack输出动态HTML(三)
    跟我一起学习webpack使用配置文件(二)
  • 原文地址:https://www.cnblogs.com/wongbingming/p/13776876.html
Copyright © 2011-2022 走看看