函数对象\函数嵌套\名称空间与作用域\闭包函数

函数对象

# def func():
#     print('from func')


#1、可以赋值
# f = func
# print(f)
# f()
#2、可以当作参数传给另外一个函数
# def foo(x):
#     # print(x)
#     x()
# foo(func)

#3、可以当作函数的返回值
# def foo(x):
#     return x          # 返回func函数的内存地址
# res=foo(func)      # 当作foo函数的参数  传入函数的内存地址
# print(res)
#4、可以当作容器类型的元素
# l=[func,]     #可以当作列表里面的元素,本质是内存地址存放在列表中
# print(l)
# l[0]()        # 从列表找到函数内存地址   \括号引用

函数嵌套

函数嵌套的调用

# 函数的嵌套调用

# def max2(x,y):
#     if x >y :
#         return x
#     else:
#         return y
#这是比较两个参数的函数  功能是比较出来大的有返回值
# def max4(a,b,c,d):
#     res1=max2(a,b)
#     res2=max2(res1,c)
#     res3=max2(res2,d)
#     return res3
# print(max4(1919,2222,3423,789))
# 这个是把上面的比较两个参数大小的函数  嵌套到另一个函数里面 比较多个参数的大小

函数嵌套的定义

# 函数的嵌套定义
#例子1
# def f1():
#     x=10
#     def f2():
#         print('from f2')
# f1()
# print(x)      变量定义在内部 外部访问不到
# print(f2)      变量定义在内部 外部访问不到

# 例子2
# def f1():
#     x=10
#     def f2():
#         print('from f2')
#     print(x)
#     print(f2)
#
# f1()

名称空间与作用域

名称空间与作用域的关系是在函数定义阶段(扫描语法时)就确立的,与什么时候调用以及调用位置无关

名称空间

名称空间namespaces:存放名字与内存地址关系的地方

大致分为:

内置名称空间:存放内置的名字
        生命周期:python解释器启动则产生,关闭则删除
全局名称空间:存放的是顶级的名字
        生命周期:运行python文件则产生,运行完毕则销毁
局部名称空间:存放的是函数内的名字
        生命周期:调用函数则产生,函数调用完毕则销毁

核心:

名称空间的加载顺序是:内置名称空间->全局名称空间->局部名称空间,而查找一个名字,必须从三个名称空间之一找到,查找顺序为:局部名称空间->全局名称空间->内置名称空间。

1、内置名称空间

伴随python解释器的启动/关闭而产生/回收,因而是第一个被加载的名称空间,用来存放一些内置的名字,比如内建函数名

print(len)
>>><built-in function len>  # built-in 内置

2、全局名称空间

伴随python文件的开始执行/执行完毕而产生/回收,是第二个被加载的名称空间,文件执行过程中产生的名字都会存放于该名称空间中,如下名字

    x = 10
    y = 20
    if 1 > 0:
        z = 30
    with open('a.txt', mode='wt') as f:
        a = 333

    while True:
        c = 444

3、局部名称空间

伴随函数的调用/结束而临时产生/回收,函数的形参、函数内定义的名字都会被存放于该名称空间中

    x = 10
    def foo(m):
        # m = 111
        n=222
    # foo(111)

核心:再次强调!

名称空间的加载顺序是:内置名称空间->全局名称空间->局部名称空间,而查找一个名字,必须从三个名称空间之一找到,查找顺序为:局部名称空间->全局名称空间->内置名称空间。

作用域

全局作用域:内置名称空间+全局名空间

特点:全局存活,全局有效

局部作用域:局部名称空间

特点:临时存活,局部有效

LEGB

LEGB 代表名字查找顺序: locals -> enclosing function -> globals -> __builtins__
locals 是函数内的名字空间,包括局部变量和形参
enclosing 外部嵌套函数的名字空间(闭包中常见)
globals 全局变量,函数定义所在模块的名字空间
builtins 内置模块的名字空间

全局作用域

全局作用域:位于全局名称空间、内建名称空间中的名字属于全局范围,该范围内的名字全局存活(除非被删除,否则在整个文件执行过程中存活)、全局有效(在任意位置都可以使用);

局部作用域

局部作用域:位于局部名称空间中的名字属于局部范围。该范围内的名字临时存活(即在函数调用时临时生成,函数调用结束后就释放)、局部有效(只能在函数内使用)。

global

#global
# 案例1
# l = []   # 当全局变量是一个可变类型  可以从局部空间改变
# def func():
#     # l.append(1111)
#     ####  如果用global就能改  记住改是针对可变类型和重新定义不同
#     l = [11,22,33]   #这样相当于在局部新定义一个变量
#
# func()
# print(l)

# 案例2:
# x=111
# def func():   #无法在局部空间更改全局的不可变类型变量
#
#     x =222
# func()
# print(x)    #>>>111

#用 global 改
# x=111
# def func():
#     global x  #  改全局变量  声明
#     x =222
# func()
# print(x)   #>>>222

nonlocal

# nonlocal
#  只会在函数里面外层 不会去全局查找
x = 111
def f1():
    x = 222
    def f2():

        nonlocal x  # 改外层函数  不会到全局
        x =333

    f2()
    print(x)  # 这是打印的222  现在想把他内层33改为22
f1()

闭包函数

闭包函数的含义:

# 闭包函数
# 闭:指的是该函数是定义在函数内的函数
# 包:指的就是该函数引用了e层函数作用域的函数

闭包函数的定义:

def outter():
    x = 111
    def wrapper():
        print(x)

    return wrapper # 千万别加()

如何给函数传参?

# 方案一:直接用参数传
# def wrapper(x):
#     print(x)
# wrapper(111)
# wrapper(222)
# wrapper(333)
#方案二:闭包函数
# def outter (x):
#     def wrapper():
#         print(x)
#     return wrapper
# f1=outter(11111)
# f1()
#
# f2=outter(222)
# f2()
posted @ 2020-12-29 15:48  williamgess  阅读(100)  评论(0编辑  收藏  举报