函数嵌套 闭包 与 函数作用域

一、作用域

  函数的命名空间可以作用域可以划分为:LEGB四种,使用缩进来规定。  不同的命名空间的变量可以同名。

    本地  local      本地使用,在函数缩进中,代表着本地缩进

    封闭  enclosing    在嵌套函数中使用,

    全局  global    任何地方都能使用,模块的顶层

    内置  Builtin       内置,比如 int,内置函数等。

1.1 作用域的范围 与 搜索次序

  

  从里到外所搜: 本地 -》封闭-》全局

1.2 作用域规则

  搜索规则 本地 -》封闭-》全局   从里到外 一层层修改。

  修改规则:  本地可以引用全局的变量,但是不可以修改上一级的变量。

      (注意复杂的数据结构,list,dict 修改他们的二级数值,并不算修改本身。详见:深浅拷贝章节)

i = 1
def test():
    i += 1   # 等同与 i = i + 1 ,这里的i 都是全局变量。 在规则中,不可以修改全局变量。
 
test()    

UnboundLocalError: local variable 'i' referenced before assignment                 

对于复杂结构的数据:

li = [1,2,3,4]
def test():
    li[0] = 100
    li.append(200) #  对于复杂的数据节后,可以直接修改二级的,并不算修改本身
test()
print(li)

结果:
[100, 2, 3, 4, 200]

 

二、内嵌函数

  在一级函数内部,定义函数,可在内部直接运行函数,也可以返回函数,这就是内嵌函数,也叫做封闭作用域。

def cal(a, b):
    def add(a,b):
        print (a+b)
    def sub(a,b):
        print(a-b) 
    def mul(x,y):
        print (a*b)

    add(a,b)
    sub(a,b)

    return mul
cal(1,3)()

 

三、闭包函数

  闭包函数是内嵌函数的升级版本,  返回  内嵌函数名 与 自由变量(非全局变量,是一级函数的变量)的绑定体。

  一般函数执行完毕,内部的变量的就消亡了,但是闭包的函数的存在一个封闭空间,不会在一级函数运行完毕而消亡。

def hellow():
    s = 'i AM'      # 自由变量
    def say():
        print(s)
    return say      # 返回内嵌函数名,但是绑定了自由变量
x = hellow()
x()

闭包函数 也遵循了,不能修改上一级变量的特征。

def hellow():
    s = 'i AM'
    def say():
        s += ''   #修改上一级变量,报错
        print(s)
    return say
x = hellow()
x()
运行结果:
UnboundLocalError: local variable 's' referenced before assignment

 

四、修改上一级的变量

  上面一直说不能修改和赋值,那一定要修改和赋值呢?  

  python中引进了  gloable 和 nolocal 两个关键字。

4.1 global

global的两个作用:

  • 声明一个全局变量

  • 在局部作用域想要对全局作用域的全局变量进行修改时,需要用到 global(限于字符串,数字)

 

def func():
    global a            #声明为全局变量
    a = 2
    print(a)

func()
print(a)

计算结果:
2
2

 

4.2 nolocal

  • 不能修改全局变量
  • 在局部作用域中,对父级作用域(或者更外层作用域非全局作用域)的变量进行引用和修改,并且引用的哪层,从那层及以下此变量全部发生改变
def add_b():
    b = 42
    def do_global():
        b = 10
        print(b)
        def dd_nonlocal():
            nonlocal b  # 只对上一层起作用
            b = b + 20
            print(b)
        dd_nonlocal()
        print(b)
    do_global()
    print(b)

add_b()


计算结果:
10
30
30
42

 

 

  

  

 

 

 

     

posted @ 2018-04-26 16:42  娄先生  阅读(658)  评论(0编辑  收藏  举报
levels of contents