装饰器学习笔记1:函数的作用域

 恩,继续整理笔记,因为不熟练,感觉平时本能的不去用这个东西,汗一个先.
 发现对这里还是有时会发生混乱. 教程里各位前辈通用说法是搞懂3大前置知识后就比较容易理解了,主要是下面3个:
函数、函数作用域、闭包

 个人觉得简单的装饰器还是比较容易理解的,复杂的地方在于给装饰器加参数后,涉及嵌套层数问题,尤其层数超过3层时,逻辑很容易弄乱了,复杂程度是成倍上升,脑子不够用啊./(ㄒoㄒ)/~~
 额,从头复习一下.函数跳过
 装饰器本质还是一个函数,不过是一个复杂的嵌套函数,而且参数和返回值也可能是一个函数.这就比较难搞了点.

1. 函数作用域

def func():
    age = 20
>>>print(age)
NameError: name 'age' is not defined

直接报错,age是一个局部变量,只作用于函数内部,这里依据LEGB原则为L,变量搜索的优先级顺序依次是LEGB,
这里个人理解为程序已经在L级别的作用域中找到变量age,所以不会继续进行下一级的搜索.当函数执行完后,已经超出变量的作用域.这时只会在E级作用域中进行搜索,所以自然是找不到的.

L:local,局部作用域,函数中定义的变量
E:enclosing,嵌套的父级函数的局部作用域,即包含此函数的上级函数的局部作用域,但不是全局的
G:globa,全局变量,就是模块级别定义的变量
B:built-in,系统固定模块里面的变量,比如int,

def func():
    class_num = 5
    def inner():
        age = 20
    print(class_num,age)
    return inner
>>>func()
<ipython-input-21-826639bd4f41> in func()
      3     def inner():
      4         age = 20
----> 5     print(class_num,age)
      6     return inner
NameError: name 'age' is not defined

 这里用ipython3运行,可以看到print这一句出错,按上面LEGB原则,这是因为name作用域为inner内部的L级局部作用域,print语句这里则为上一级的E级,也就是嵌套的父级函数的局部作用域,所以报错.
改造一下函数:

def func():
    class_num = 5
    def inner():
        age = 20
        print(class_num,age)
    return inner
>>>a = func()
>>>a()
5 20

 这时可以看到正常输出了class_num和age,按照LEGB的原则,变量搜索的优先级顺序依次是LEGB,也就是先从age所在的L级作用域搜索,这时找到age,L级没有class_num,继续搜索E级作用域,成功找到class_num,则print语句正常执行 .
综合上面,
这里个人理解为可以从当前作用域层级向上级查找搜索变量,但不能向下级搜索.

name = 'lili'
def func():
    class_num = 5
    def inner():
        age = 20
        print('班级:{}班 姓名:{} 年龄{}'.format(class_num,name,age))
    return inner
>>>a = func()
>>>a()
班级:5班 姓名:lili 年龄:20

可以看到,name是更上一层的G级,即全局变量,可以在内部调用.
如果想在函数内部修改全局变量,可以用global关键字

name = 'lili'
def func():
    class_num = 5
    def inner():
        global name
        age = 20
        name = 'wang'
        print('班级:{}班 姓名:{} 年龄{}'.format(class_num,name,age))
    return inner
>>>a = func()
>>>a()
班级:5班 姓名:wang 年龄:20

这时就将上层的全局变量修改了,同样,如果要修改父级局部作用域的局部变量class_num,可以用另一个关键字nonlocal

name = 'lili'
def func():
    class_num = 5
    def inner():
        nonlocal class_num
        age = 20
        class_num = 8
        print('班级:{}班 姓名:{} 年龄{}'.format(class_num,name,age))
    return inner
>>>a = func()
>>>a()
班级:8班 姓名:lili 年龄:20

小结:
作用域共有4级,按优先级顺序依次是LEGB
L:local,局部作用域,函数中定义的变量
E:enclosing,嵌套的父级函数的局部作用域,即包含此函数的上级函数的局部作用域,但不是全局的
G:globa,全局变量,就是模块级别定义的变量
B:built-in,系统固定模块里面的变量,比如int,

可以从当前作用域层级向上级查找搜索变量,但不能向下级搜索.
调用的上级变量是不能直接进行赋值更改的,
要更改时必须用关键字 global 和 nonlocal
分别对应全局变量和父级局部作用域变量

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值