闭包中的nonlocal和global以及不使用nonlocal

2018-11-01  本文已影响0人  Elvis_zhou

effective-python中,在阐述作用域变量时提到了nonlocal和global,当提到python2没有nonlocal时,实现了其功能,这例子没读懂:

# Python2
def sort_priority(values, group):
    found = [False]
    def helper(x):
        if x in group:
            found[0] = True
            return (0, x)
        return (1, x)

    values.sort(key=helper)
    return found[0]

重中之重:基础,赶紧查查资料:

1. 全局变量与局部变量

全局变量为定义在函数外部的变量
局部变量为定义在函数内部的变量

2. 定义

golobal 指定全局变量
nonlocal 指定上一级变量

3. 特性

参考链接:https://www.cnblogs.com/echoboy/p/8973266.html

4. 注意点:

global是作用在全局的,并不能修改函数内的变量!

found = 9


def line_conf():
    found = "nihao"

    def line():
        # nonlocal found
        global found
        found = "hello"
        print('found1:', found, id(found))

    line()
    print('found2:', found, id(found))

print('found0:', found, id(found))
line_conf()
print('found3:', found, id(found))

### 打开global:###
found0: 9 10919680
found1: hello 139819150299184
found2: nihao 139819150391592
found3: hello 139819150299184

### 打开nonlocal:###
found0: 9 10919680
found1: hello 140527291113520
found2: hello 140527291113520
found3: 9 10919680

这个栗子很好的体现了global和nonlocal的作用范围,更体现了一点:当被global和nonlocal定义之后,变量的值是直接修改的。

在闭包中,内嵌函数是可以读上层变量,但是不可写的:

def line_conf():
    found = 6

    def line():
        # found = 8
        print('found1:', found, id(found))

    line()
    print('found2:', found, id(found))

line_conf()

###  found = 8 注释了 ###
found1: 6 10919584
found2: 6 10919584

###  打开 found = 8  ###
found1: 8 10919648
found2: 6 10919584

读到这里,之前的疑惑就可以解开了:
为什么可以用list起到nonlocal的作用?
因为found变量在内层函数是不可以写上一层的,但是可以读(因为没修改id),所以我们把found设置成列表,让解释器去上一层读取这个列表(也就是说只要在不改变id的前提下就可以拿到上层的变量),注意!上面的栗子证明,nonlocal和global都是直接修改变量的(也就是id),列表的修改是不改变id的,所以,在这里使用列表也可以达到nonlocal的效果。

 Python2
def sort_priority(values, group):
    found = [False]
    def helper(x):
        if x in group:
            found[0] = True
            return (0, x)
        return (1, x)

    values.sort(key=helper)
    return found[0]

print('Found:', sort_priority(values, group))
print(values)

###       ###
Found: True
[7, 9, 1, 2, 3, 4, 5, 6, 8]
上一篇下一篇

猜你喜欢

热点阅读