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

函数对象: 

  函数是第一类对象,即函数可以当做数据传递

    1 可以被引用

    2 可以当做参数传递

    3 返回值可以是函数  (函数名 不带() 就是函数名的内存地址,带括号就是执行函数)

    4 可以当做容器类型的元素

def foo():
    print('foo')

def bar():
    print('bar')

dic={
    'foo':foo,
    'bar':bar,
}
while True:
    choice=input('>>: ').strip()
    if choice in dic:
        dic[choice]()

def func(): # func=函数的内地址
print('from func')
age=10
# 1. 可以被引用
# x=age
# print(x,age)

# f=func
# print(f)
# f()

# 2. 可以当作参数传给另外一个函数
# def bar(x):
# print(x)

# bar(age)
# bar(func)

# 3. 可以当作一个函数的返回值
# def bar(x):
# return x

# res=bar(age)
# print(res)

# res=bar(func)
# print(res)

# 4. 可以当作容器类型的元素
# l=[age,func,func()]
# print(l)

 

利用函数的特性取代多分支的if

def foo():
    print('foo')

def bar():
    print('bar')

dic={
    'foo':foo,
    'bar':bar,
}
while True:
    choice=input('>>: ').strip()
    if choice in dic:
        dic[choice]()

函数的嵌套

函数的嵌套定义:一个函数内部又定义了另一个函数
def f1():
    def f2():
        def f3():
            print('from f3')
        f3()
    f2()


f1()
f3() #报错 空间与作用域

函数的嵌套调用 :在调用一个函数过程中,内部代码又调用了其他函数
def max(x,y):
    return x if x > y  else y

def max4(a,b,c,d):
    res1=max(a,b)
    res2=max(res1,c)
    res3=max(res2,d)
    return res3
print(max4(1,2,3,4)

名称空间与作用域

  什么是名称空间: 存放名字的地方,三种名称空间(内置 全局 局部)

  名称空间的加载顺序

    python test.py

    1 python解释器先启动,因而首先加载的是:内置空间

    2 执行test.py文件,然后以文件为基础,加载全局名称空间

    3 执行文件的过程中如果调用函数,则临时产生局部名称空间

  名字的查找顺序

    局部名称空间———》全局名称空间——》内置名称空间 (在全局无法查看局部的,在局部可以查看全局的)

# max=1
def f1():
    # max=2
    def f2():
        # max=3
        print(max)
    f2()
f1()
print(max)

作用域

#1、作用域即范围
        - 全局范围(内置名称空间与全局名称空间属于该范围):全局存活,全局有效
      - 局部范围(局部名称空间属于该范围):临时存活,局部有效
#2、作用域关系是在函数定义阶段就已经固定的,与函数的调用位置无关,如下
x=1
def f1():
    def f2():
        print(x)
    return f2
x=100
def f3(func):
    x=2
    func()
x=10000
f3(f1())

#3、查看作用域:globals(),locals()


LEGB 代表名字查找顺序: locals -> enclosing function -> globals -> __builtins__
locals 是函数内的名字空间,包括局部变量和形参
enclosing 外部嵌套函数的名字空间(闭包中常见)
globals 全局变量,函数定义所在模块的名字空间  将局部变量的作用域提升至全局作用域,可以用来在局部修改全局的不可变类型
builtins 内置模块的名字空间

nonlocal 声明一个名字是来自于当前层外一层作用域的,可以用来在局部修改外层函数的不可变类型将L 与 E 中的名字统一需要提前定义

!!!名字的查找顺序,在函数定义阶段就已经固定死了(及在检测语法是就已经确定了名字的查找顺序),与函数的调用位置无关,也就是说无论在任何地方调用函数,都必须回到当初定义函数的位置去确定名字的查找关系

x=111
def outer():
    def inner():
        print('from inner',x) # x访问的时全局名称空间中x
    return inner

f=outer()        <function outer.<locals>.inner at 0x00000000021DB6A8>
print(f)           from inner 222

x=222
f()                  222  访问时全局的x已经被重新赋值了

x=111
def outer():
    def inner():
        print('from inner',x) # x访问的时全局名称空间中x
    return inner
  
f=outer()           from inner 444  全局被重新赋值为444

# x=222
def func():
    x=333
    f()

x=444
 
func()    func->f->outer->x 全局变量 444     from inner 444
posted @ 2019-04-02 15:42  读自己  阅读(109)  评论(0编辑  收藏  举报