名称空间与作用域

一、函数对象

  函数是第一类对象

  1、函数名是可以被引用

1 def func():
2     print('from func')
3 a = func
4 a()

  2、函数名可以当做参数传递

1 def index(x, y, func):
2     print(x, y)
3     func()
4 def foo():
5     print('from foo')
6 index(1, 2, foo)

  3、函数名可以当做返回值使用

1 def index():
2     print('from index')
3 def func(a):
4     return a
5 b = func(index)
6 b()

  4、函数名可以被当做容器类型的元素

1 def func():
2     print('from func')
3 a = [1, '2', func]
4 f = a[2]
5 f()
 1 # 简单购物车
 2 def register():
 3     print('register')
 4 def login():
 5     print('login')
 6 def shopping():
 7     print('shopping')
 8 def pay():
 9     print('pay')
10 def logout():
11     print('logout')
12 func_dict = {
13     '1': register,
14     '2': login,
15     '3': shopping,
16     '4': pay,
17     '5': logout
18 }
19 def main():
20     while True:
21         print('''
22         1、注册
23         2、登录
24         3、购物
25         4、付款
26         5、退出
27         ''')
28         choice = input(">>>>").strip()
29         if choice == '5':
30             func_dict[choice]()
31             break
32         elif choice not in func_dict.keys():
33             continue
34         else:
35             func_dict[choice]()
36 main()

二、名称空间

  名称空间即存放名字与对象映射/绑定关系的地方。例如x=3,python会申请内存空间存放3,然后将名字x与3的绑定关系存放于名称空间中,执行时候会存在三种名称空间

  名称空间分类:

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

    ⑵、全局名称空间:伴随着pytho文件的开始执行而产生,执行完毕而回收,是第二个被加载的名称空间,文件执行过程中产生的名字都会存放于该名称空间中

    ⑶、局部名称空间:伴随着函数的调用而尝试,函数结束调用而回收,函数的形参、函数的定义的名字都会被存在于该名称空间中

  名称空间顺序:

      加载顺序:内置名称空间 > 全局名称空间 > 局部名称空间

      查找顺序:局部名称空间 > 全局名称空间 > 内置名称空间

    函数内部使用的名字,在定义阶段就已经规定死了,与你的调用位置无关

 1 x = 1
 2 def dex():
 3     print(x)
 4 def func():
 5     x = 2
 6     dex()
 7 func()
 8 # 输出:1
 9 
10 x = 1
11 def index(arg = x):
12     print('x =', x, 'arg =', arg)
13 x = 2
14 index()
15 # 输出:x = 2 arg = 1

三、作用域

  1、全局作用域与局部作用域

    全局作用域:位于全局名称空间、内置名称空间中的名字属于全局范围。该范围内的名字全局存活、全局有效(在任意位置都可以使用)

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

  2、作用域与名字查找的优先级

    ⑴、在局部作用域查找名字时,起始位置是局部作用域,所以先查找局部名称空间,没有找到,再去全局作用域查找:先查找全局名称空间,没有找到再查找内置名称空间,最后没找到抛出异常

    ⑵、在全局作用域查找名字时,起始位置时全局作用域,所以先查找全局名称空间,没有找到再查找内置名称空间,最后没找到抛出异常

    ⑶、python支持函数的嵌套定义,在内嵌的函数查找名字时,会优先查找自己局部作用域的名字,然后由内而外一层层查找外部嵌套函数定义的作用域,都没有找到,则查找全局作用域

x = 1
def func():
    x = 2
    def index():
        x = 3
        print('内层:',x)
    index()
    print('外层:',x)
func()
# 结果为
内层:3
外层:2

    在函数内,无论嵌套多少层,都可以查看到全局作用域的名字,若要在函数内修改全局名称空间的名字值,需要用到global关键字

1 x = 1
2 def func():
3     global x
4     x = 2
5 func()
6 print(x)
7 # 输出结果:2

    对于嵌套多层的函数,使用nonlocal关键字可以将名字声明为来自外部嵌套函数定义的作用域(非全局)

 1 def f1():
 2     x = 1
 3     def f2():
 4         x = 2
 5         def f3():
 6             x = 3
 7             def f4():
 8                 nonlocal x
 9                 x = 4
10                 print('f4:', x)
11             f4()
12             print('f3:', x)
13         f3()
14         print('f2:', x)
15     f2()
16     print('f1:', x)
17 f1()
18 # 输出结果:
19 f4:4
20 f3:4
21 f2:2
22 f1:1

    ps:只有可变类型可以在局部修改外部变量的值

      不可变类型的局部变量的修改无法影响上层,上上层

posted @ 2019-11-11 16:41  treeter  阅读(250)  评论(0编辑  收藏  举报