Day10 local、global、局部变量的修改、闭包函数、嵌套函数

1.locals 获取当前作用域的所有变量

locals 如果在函数的外面,获取locals()返回值打印之前, 所有的内容.
# 获取打印返回值之前的所有内容
a = 10
b = 20
res = locals()
c=20
print(res)
# 内置的没有写出来
# 'a': 10, 'b': 20, 'res': {...}, 'c': 20}
 
locals 如果在函数的里面,获取locals调用之前,所有的内容
# 获取locals调用之前的所有的内容
def func():
    f1 = 11
    f2 = 12
    res = locals()
    f3 = 13
    print(res)
func()
# {'f2': 12, 'f1': 11}
2.globals 只获取全局变量(无论在函数内外都只获取全局变量)
globals 返回的是系统的 全局命名空间的字典 ,在空间里面放的全局变量'''
globals 如果在函数的外面,获取globals()返回值打印之前, 所有的内容.
globals 如果在函数的里面,获取globals调用之前,所有的内容
z1 = 5
z2 = 6
def func1():
    f1 = 1
    f2 = 2
    f3 = 3
    res = globals()
    f4 = 6
    print(res)
z4 = 8
func1() #res = globals()
# 内置太多没有给出
# 'z1': 5, 'z2': 6, 'func1': <function func1 at 0x00000000027E3D08>, 'z4': 8

 3.globals 可以批量创建全局变量

def func():
    res = globals()
    # res['a1'] = 1
    # res['a2'] = 2
    for i in range(5):
        # print(i)
        res["a%d" % (i) ] = i
        '''
        "a%d" % (i)  # 字符串的格式化
        
        res['a0'] = 0
        res['a1'] = 1
        res['a2'] = 2
        res['a3'] = 3
        res['a4'] = 4
        '''
        
func()
print(a0)
print(a1)
print(a2)
print(a3)
print(a4)
# 0
# 1
# 2
# 3
# 4

# locals 更多的用于获取一些变量 , globals更多的用于修改一些变量

函数的嵌套

'''
嵌套在外层,称之外函数
嵌套在里层,称之内函数
'''

嵌套1:

def outer():
    
    def inner():
        print("我是inner函数")
    inner()
outer()
# 我是inner函数

嵌套2:

# 外层函数outer 里面是inner , inner里面还嵌套一个smaller内函数 ,调用smaller
# a = 17
def outer():
    # a = 16
    # id = 99
    def inner():
        # a = 15
        def smaller():
            # a = 10
            print(id)
            print("我是smaller函数")
        smaller()
            
    inner()
            
            
outer()            

1.LEGB (就近找变量原则)

'''    
#找寻变量的调用顺序采用LEGB原则(即就近原则)
B —— Builtin(Python);Python内置模块的命名空间      (内建作用域)(内建命名空间)
G —— Global(module); 函数外部所在的命名空间        (全局作用域)(全局命名空间)
E —— Enclosing function locals;外部嵌套函数的作用域(嵌套作用域)(局部命名空间)
L —— Local(function);当前函数内的作用域            (局部作用域)(局部命名空间)
依据就近原则,从下往上 从里向外 依次寻找
'''        
# 额外注意点
'''如果先前局部变量存在a,删除之后在获取就获取不到,
如果先前不存在该局部变量,默认向上按照LEGB原则依次寻找
'''
a = 10
def func():
    a = 20
    del a
    # print(a) error
func()
# print(a)

3.nonlocal 修改局部变量

'''
nonlocal 专门用于修改局部变量
    (1)它自动寻找上一层空间的局部变量用来修改
    (2)如果上一级也没有,在不停的向上寻找
    (3)如果再也找不到了,直接报错
'''
(1) nonlocal 修改的是局部变量,不是全局变量.
(2) 不使用nonlocal 是否可以修改局部变量?
可以。
def outer():
    # a  = 3 
    lst = [1,2,3,4,5]
    def smaller():
        lst[2] += 5
    smaller()
    print(lst)
    
outer()
#[1, 2, 8, 4, 5]
# 注意点:
'''
# a = 20
def outer():    
    a = 81
    def inner():
        global a
        a = 16
        def smaller():
            # nonlocal a
            # print(a)  # 获取a
            # global a
            # a+=3
            # 上一级找到的是一个全局变量,nonlocal无法修改
            nonlocal a
            print(a)
        smaller()
    inner()
outer()
'''

(3)nonlocal 符合LEGB原则

def outer():
    a = 15
    def inner():
        nonlocal a
        a = 17
        print(a)        
    inner()
    print(a)
outer()
# 17
# 17

闭包函数

'''
闭包:
    内函数使用了外函数的局部变量,
    并且外函数把内函数返回出来的过程是闭包
    这个内函数叫做闭包函数;
'''

1.基本用法

def outer():
    a = 5
    b = 6
    # inner 是闭包函数
    def inner():
        print(a,b)
    return inner
res = outer()  # res = inner
print(res)
# <function outer.<locals>.inner at 0x0000000001E83D08>
res()          # res() = inner()
# 5 6
# 获取闭包函数使用的变量  __closure__ , cell_contents (了解)(函数还是上面的那个函数)
tup = res.__closure__
print(tup)
# (<cell at 0x0000000001DF76D8: int object at 0x0000000055A46C90>, <cell at 0x0000000001DF7708: int object at 0x0000000055A46CB0>)
# 获取元组里面第一个元素
obj = tup[0]
print(obj)
# <cell at 0x0000000001DF76D8: int object at 0x0000000055A46C90>
# 使用cell_contents来获取单元对象当中的值
res = obj.cell_contents
print(res)
# 5
obj2 = tup[1]
res2 = obj2.cell_contents
print(res2)
# 6

 闭包的特点

# 闭包的特点:
"""
    内函数使用了外函数的局部变量,外函数的局部变量与内函数发生绑定,延长该变量的生命周期
    (实际内存给它存储了这个值,暂时不释放)
"""
def majunqiang_family():
    dajie = "马蓉"
    erjie = "马冬梅"
    kuang = "金矿"
    # money 局部变量因为在闭包函数中使用,于是发生绑定,延长该变量的生命周期
    money = 1000
    
    def dajie_hobby():
        nonlocal money
        money -= 900
        print("大姐喜欢花钱,喜欢买兰博基尼,喜欢买比基尼,喜欢买channel,家里钱还剩下%d" % (money))

    def erjie_hobby():
        nonlocal money
        money += 500
        print("二姐马冬梅喜欢赚钱,喜欢上长春扎疫苗,因为假疫苗能赔偿,喜欢卖血,5块钱一瓶,家里钱赚了%d" % (money))

    def master():
        # 返回一个元组,元组里面的每一个元素是函数
        return (dajie_hobby,erjie_hobby)
        
    return master


func = majunqiang_family()
tup = func()
print(tup)
# (<function majunqiang_family.<locals>.dajie_hobby at 0x0000000001E83D90>, <function majunqiang_family.<locals>.erjie_hobby at 0x0000000001E83E18>)
# 大姐函数
dajie = tup[0]
dajie()
# 大姐喜欢花钱,喜欢买兰博基尼,喜欢买比基尼,喜欢买channel,家里钱还剩下100
# 二姐函数
erjie = tup[1]
erjie()
# 二姐马冬梅喜欢赚钱,喜欢上长春扎疫苗,因为假疫苗能赔偿,喜欢卖血,5块钱一瓶,家里钱赚了600

例2:

def outer(num):
    
    def inner(val):
        return num + val
    return inner
    
func = outer(10)  # func = inner
res = func(21)   # func(21) = inner(21)
print(res)       # res = num + val =  10 + 21 = 31
# 31

闭包的意义:

# 模拟鼠标点击的操作
# 如果使用全局变量num来进行统计,因为作用域太大,容易造成漏洞.不安全
num = 0
def click_num():
    global num
    num+=1
    print(num)
# 调用一次函数,累加一次num
click_num()
click_num()
click_num()

num = 100
click_num()
click_num()
# 1
# 2
# 3
# 101
# 102
# 闭包的意义:
'''
闭包可以优先使用外函数中的变量,并对闭包中的值起到了封装保护的作用.外部无法访问.
'''
def click_num():
    num = 0
    def func():
        nonlocal num
        num +=1
        print(num)
    return func

click_num = click_num()
click_num()
click_num()
click_num()
num = 100
click_num()
click_num()
# 1
# 2
# 3
# 4
# 5

猜你喜欢

转载自www.cnblogs.com/longerandergou/p/10959695.html