D10 函数(二) 嵌套,命名空间作用域

1 :函数是第一类对象:函数名指向的值可以被当作参数传递

  1. 函数名可以被传递
    def f():
        return 2
    
    print(f())  # 2
    print(id(f))  # 2707674798688
    f1 =f  # 将f函数的内存地址赋值给f1  f1与f 指向的是同一内存地址
    print(f1())  # 2
    print(id(f)) # 2707674798688
  2. 函数名可以被当作参数传递给其他函数
    def f():
        print("我是f")
    
    
    def f1(args):  # 将f的内存地址作为参数传到f1中
        print(args)  # <function f at 0x000001A6C0C19A60>
        args()  # 我是f
        print("我是f1")  # 我是f1
    
    
    print(f)  # <function f at 0x000001A6C0C19A60>
    f1(f)
  3. 函数名可以作为返回值返回
    def f():
        print("我是f")
    
    def f1():
        print("我是f1")
        return f
    
    res = f1()  # 先执行f1()函数,然后将f的内存地址返回,res接收
    res()  # 这里相当于调用f()   我是f
  4. 函数名可以被当作容器类型参数
    def f():
        print("我是f")
    
    
    print(f)  # f的内存地址
    l = [1, 2, f, f()]  # 有括号的优先,所以先调用f() ,输出我是f后返回None
    print(l)  
    '''
    <function f at 0x000002643FDF9A60>    
    我是f
    [1, 2, <function f at 0x000002643FDF9A60>, None]
    
    '''

2. 函数的嵌套:

  1. 函数的嵌套调用:在函数的内部调用其他函数,可以使使逻辑变得简单
    def my_max(x,y):
        if x > y:
            return x
        return y
    
    
    def my_max_long(a,b,c,d):
        res = my_max(a,b)   # 在内部调用my_max函数
        res1 = my_max(res,c)
        res2 = my_max(res1,d)
        return res2
    
    
    print(my_max_long(9,32,435,3423))  # 3423

     

  2. 函数的嵌套定义:该函数用户可以通过传参的不同控制函数执行不同的功能
    def outer():
        print("我是outer")
        def inner():
            print("我是inner")
        return inner
    
    res = outer()   # 先执行outer()  res 接收的是inner的内存地址
    res()   # 相当于调用了inner

     

3. 命名空间:存放的是变量名与变量值的内存地址得绑定关系的地方要想访问一个变量的值 必须先去名称空间中拿到对应的名字       才能够访问变量的值

 

  1. 命名空间的分类:内置命名空间:python解释器提前定义好的名字,如:len , print

             全局命名空间:在py文件大局上定义的变量,if for while 无论嵌套多少层 它们内部所创建的名字都是全局名称空间的

x = 1   # 为全局命名空间的变量
def f():
    z = 3

           局部命名空间:函数体内创建的名字都属于局部名称空间

x = 1
def f():
    z = 3   # 局部内存空间的变量

 

  1. 命名空间的生命周期:

          内置命名空间:在python解释器运行就立即创建,关闭解释器则销毁

          全局命名空间:在运行Py文件时创建,程序结束销毁

          局部命名空间:在调用函数时创建,函数结束销毁

  1. 命名空间的查找顺序:在全局命名空间的时候先找全局再找内置,在局部命名空间时先找局部再找全局最后在找内置,函数在定义阶段查找名字的顺序就已经固定了 不会因为函数的调用位置变化而改变

 

def f():
    x = 50
    def f1():
        def f2():
            print(x)
            # NameError: free variable 'x' referenced before assignment in enclosing scope
            # 会报错因为在函数定义阶段查找名字的顺序就已经固定了,所以他不会找f函数里的x,因为在f2中已经存在X
            # 所以只会像上层找,而上层是先调用后赋值的,所以报错
        f2()
        x = 100
    f1()

f()

4.作用域:作用域就是作用范围,可分为全局作用域和局部作用域

    1:全局作用域:作用在全局,在整个文件中都能被引用。全局有效

    2:局部作用域:作用在局部,只能在局部生效,函数

    3:在局部空间修改全局变量:用global

      不用global的情况下:

a = 1
def func():
    a = 2       # 在内部直接修改


func()
print('a:%d' % a)        # a:1 a没有改变

      使用global的情况下:

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


func()
print('a:%d' % a)        # a:2 修改成功

      在全局变量为可变类型时:

a = [1]
def func():
    a.append(2)


func()
print('a:{}'.format(a))        # a:[1,2] 修改成功

    4:在局部修改局部变量:nonlocal

def f1():
    a = 1
    def f2():
        nonlocal a
        a += 1
        print(a)
    f2()
f1()    # 结果为2 修改成功

      

def f1():
    a = 1
    def f2():
        a = 2
        def f3():
            nonlocal a  # 只对上一层的作修改
            a += 1
            print(a)
        f3()
    f2()

f1()       # 结果为 3 修改的是f2() 中的变量a

 

 

posted @ 2019-07-10 18:26  人生能有几回搏  阅读(190)  评论(0编辑  收藏  举报