DAY10 函数的进阶(命名空间,作用域,函数嵌套)

前提须知(python解释器遇到函数的做法):

  1.从python解释器开始执行后,就在内存中开辟了一块空间(全局命名空间)。

  2.每次遇到一个变量的时候,就会把这个变量名和值得对应关系保存到这个内存的一个字典中,记录下来。

  3.但是遇到函数定义的时候,解释器只会象征性地把函数读入内存,表示知道这个函数的存在,但是对函数内部的“变量”和逻辑毫不关心。

  4.等执行到函数调用的时候,python解释器就会再开辟一块内存来存储函数里面的内存(局部命名空间)。这个时候,才会真正开始关注函数里面有哪些变量,而函数的变量会存储到新开辟的这个内存中。函数的变量只能在函数的内部使用,而且随着函数的执行完毕,这块空间就会被回收,内容就会被清空。

 

一.三种命名空间

  1. 全局命名空间

  2. 局部命名空间

  3. 内置命名空间

从上面的解释,我们可以得出:

(1)代码开始时,python解释器创建的存储“变量:值”对应关系的内存空间叫做全局命名空间。

(2)在函数开始执行时,python解释器在内存中新开辟的内存空间叫做局部命名空间。

(3)内置命名空间,python内置,例如input,print等,在哪里都可以直接拿来使用。

 

二.三种命名空间的加载和取值顺序:

  1.加载顺序:

  内置命名空间(程序运行前加载)---> 全局命名空间(程序运行中加载,由上到下)--->局部命名空间(函数调用时加载)

  2.取值顺序:

  在局部调用时:局部命名空间--->全局命名空间--->内置命名空间

  在全局调用时:全局命名空间--->内置命名空间

 

#在局部命名空间中:局部》全局》内置
#在全局命名空间中:全局》内置
#取值顺序都是单向的,不可逆。

x = 10
def foo():
    x = 20
    print(x)
foo()    #局部>全局>内置
print(x)   #全局>内置
>>>
20
10

 

  

三.作用域

  作用域就是作用范围,按照生效范围可以分为全局作用域和局部作用域等~

  LEGB:

  (1)Local(本地,局部):在局部空间中,即函数定义的变量。

  (2)Enclosing(封闭):用在函数嵌套时。

  (3)Global(全局):在当前这个py文件中

  (4)Builtin(内置):在所有py文件中都可以使用,例如:input,str等。

 

四.global关键字

  前提:局部命名空间对全局命名空间的变量可以引用,但是不能修改。

  global作用:

    1. 在局部名称空间声明一个局部变量。

    2. 在局部名称空间可以对全局变量进行修改。

#一。结合前文的取值顺序,
count = 1
def func1():
    print(count)    #取值顺序,局部命名空间(没有)----全局命名空间(有)
func1()
>>>
1

#二。如果在局部作用域中对全局变量进行修改,会如何?

count = 1
def func1():
    count = count +1
    print(count)
func1()
>>>UnboundLocalError: local variable 'count' referenced before assignment

'''
UnboundLocalError: local variable 'count' referenced before assignment
如果你在局部命名空间对一个变量进行修改,解释器就会认为这个变量要存在,已经在局部定义;如果没有
定义,就会引发以上报错。
'''
# 这个时候就是使用global的场景
# global的作用:
'''
1. 在局部命名空间声明一个局部变量。
2. 在局部命名空间对全局变量进行修改。
'''

count = 1
def func():
    global count
    count = count +1
    print(count)
func()
print(count)
>>
2
2

五.函数嵌套

  函数是python中的一级对象,可以在任何地方使用。包括函数里,此时的作用域属于封闭作用域Enclosing。

  函数名的本质:函数也是一级对象。

  一级对象

  (1)在运行时创建

  (2)能够赋值给变量

  (3)能够作为参数传递给函数

  (4)能够作为函数的返回值

#函数嵌套范例一
def f1():
    print('in f1')
    def f2():
        print('in f2')
    f2()
f1()
>>>
in f1
in f2

#函数嵌套范例二
def f1():
    def f2():
        def f3():
            print('in f3')
        print('in f2')
        f3()
    print('in f1')
    f2()
f1()
>>>
in f1
in f2
in f3

  4.1 函数嵌套的作用域链

#函数作用链(一)
def f1():
    a = 1
    def f2():
        print(a)      
    f2()
f1()
>>>
1

# 函数作用域(二)
def f1():
    a = 1
    def f2():
        def f3():
            print(a)
        f3()
    f2()
f1()
>>>
1

# 函数的作用域(三)
def f1():
    a = 1
    def f2():
        a = 2
        print('a in f2:',a)
    f2()
    print('a in f1:',a)
f1()
>>>
a in f2: 2
a in f1: 1

  总结以上:就是先从局部命名空间查找,再一级一级向上查找。

 

六.nonlocal关键字

  1.在函数的外部必须有这个变量

  2.在内部函数声明nonlocal变量之前,不能再出现同名变量。

  3.在局部作用域修改父级作用域(非全局作用域的更外层作用域),并且引用的哪层,就从那层以下此变量发生变化。

def f1():
    a = 10
    def f2():
        nonlocal a
        a = 30
    f2()
    print('in the f1:',a)
f1()
>>>
a in f2: 2
a in f1: 1
in the f1: 30


def f1():
    a = 10
    def f2():
        def f3():
            nonlocal a
            a = 30
            print('in the f3:',a)
        print('in the f2:',a)
        f3()
    f2()
    print('in the f1:',a)
f1()
>>>
in the f2: 10
in the f3: 30
in the f1: 30

  

 

posted @ 2018-08-16 16:56  hehehe1994  阅读(118)  评论(0编辑  收藏  举报