七、函数(二)

一、命名空间和变量的作用域

1、命名空间

  命名空间一共分为三种:

  全局命名空间:我理解为写代码的文件里,且除开函数的地方;

  局部命名空间:就函数内部;

  内置命名空间:Python解释器的地盘,我将其理解为整个工程文件的范围。

  内置命名空间中存放了python解释器为我们提供的函数和变量名:input,print,str,list,tuple...可以直接使用。

  三种命名空间之间的加载与取值顺序:内置命名空间(程序运行前加载)->全局命名空间(程序运行中:从上到下加载)->局部命名空间(程序运行中:调用时才加载)

  取值:在局部调用:局部命名空间->全局命名空间->内置命名空间。

2、作用域

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

  全局作用域:包含内置名称空间、全局名称空间,在整个文件的任意位置都能被引用、全局有效。

  局部作用域:局部名称空间,只能在局部范围内生效。

  2.1  global方法

    得到所有的全局变量和方法。

  2.2  locals方法

    得到调用处所有的局部变量和方法。

  2.3  global

    在局部命名空间声明一个全局变量。这个时候,可以在局部改变全局变量的值。

a = 10
print(locals())
def func():
    global a
    a = 20
    b = 20
    def func():
        pass
    print(globals())
    print(locals())
func()
print(a)

二、函数的嵌套

1、函数的嵌套调用

  在同一命名空间内的函数可以相互调用。假设函数A和B在同一命名空间内,那么可以在A中调用B,也可以在B中调用A。

def A():
    print('in func A')

def B()
    print('in func B,call A func next')
    A()
B()

 

2、函数的嵌套定义

  在函数中定义函数。为了叙述方便,称在函数里定义的函数为子函数,孙函数依此类推,定义在全局命名空间的函数为父函数。

def Fatherfunc():
    print('in father func')
    def sonfunc():
        print('in son func')
        def grandsonfunc():
            print('in grandson func')
        grandsonfunc()
    sonfunc()
if __name__ == '__main__': #表示程序的入口,详细的原因将在后面的文章中讲述
    Fatherfunc()

3、函数内部变量的作用域

   在父函数中定义的变量可以在它的所有后代函数中调用,查看,但是不可以修改其值。

def Fatherfunc():
    a = 10
    def sonfunc():
        print(a) # 10
        def grandsonfunc():
            print(a)#10
            #a=1
        grandsonfunc()
    sonfunc()
    print(a) #10
if __name__ == '__main__':
    Fatherfunc()

上例代码若将grandsonfunc()中的a=1语句取消注释程序将报错。

4、nonlocal关键字

  我们无法在函数中改变全局命名空间中的变量的值,除非使用global关键字声明一个全局变量。同理,如果我们要在函数的后代函数中修改函数的内部变量,需要用nonlocal关键字声明一个函数内的局部变量。

  值得注意的是:在某一函数内用nonlocal关键字声明了一个局部变量后,会从当前函数的父函数开始查找这个变量,查询到立即停止,如果找不到再到爷爷函数里去找,直到找到为止。若是在最外层函数也找不到这个变量就会报错。

def Fatherfunc():
    a=10
    def sonfunc():
        nonlocal a
        print(a) # 10
        a = 1
        def grandsonfunc():
            print(a)#1

        grandsonfunc()
    sonfunc()
    print(a) #1
if __name__ == '__main__':
    Fatherfunc()

三、闭包函数

  首先补充一个小知识。函数名本质上是一个变量,它存储着某一段代码在内存中的地址入口。因此,我们完全可以把函数名当作一般的变量,把它的值赋给其他的变量,放在列表、字典里面等等操作,甚至是当作参数传给另一个函数然后通过变量名()的方式调用函数。

 

  闭包函数:使用了父函数的子函数。

def func():
    a = 10
    def inner():
        print(a)

  闭包函数的作用:用于作用域,我们无法直接调用函数内部的函数。而前面已经说过函数名介绍一个变量,于是我们就可以通过return闭包函数的函数名使得可以直接调用闭包函数。

def func():
    a = 10
    def inner():
        print(a)
    return inner

if __name__ == '__main__':
    f = func()
    f()
#func()执行完的时候,返回inner,inner是函数inner()的代码地址,然后把这个地址返回并赋值给f,此时f相当于inner,f()相当于inner()

  同时,我们是可以给inner设置参数,并通过f()传参的。

posted @ 2019-03-06 11:13  Darius-xiong  阅读(107)  评论(0编辑  收藏  举报