python语法之函数对象/嵌套/名称空间/作用域
一、函数对象
1、 函数名是可以被引用的
def foo(): print('from foo') res = foo #把函数名foo给了res,res和foo指向了同一个内存地址 res() #from foo
2、函数名可以当做参数传递
def foo1(a,b): #a=1,b=foo2 print(a) #1 b() #b() 即foo2() 去执行foo2()的函数,结果:from foo2 def foo2(): print('from foo2') foo1(1, foo2) #foo2作为参数传给了b
3、函数名可以当做返回值使用
def foo(x): return x def foo1(): print('from foo1') res = foo(foo1) #把函数名foo1给了x,调用foo()函数返回foo1,然后把foo1给了res res() #res() 即是foo1()
4、函数名可以当做容器类型的元素
def func(): print('from func') l1 = [1,'2',func] l = l1[2] #即l=func l() #func()
4.1、购物车:
func_dic = { '1': register, '2': login, '3': shopping, '4': pay } def main(): while True: print(""" 1、注册 2、登录 3、购物 4、付款 5、退出 """) choice = input("请输入对应的编号:").strip() if choice == '5': break if choice not in func_dic: continue else: func_dic[choice]() main()
二、函数的嵌套
2.1、函数的嵌套调用:在函数内调用函数
2.2、函数的嵌套定义:在函数内部定于函数
三、名称空间
3.1、名称分类
3.1.1、内置名称空间:python提前给定好的名字,比如内建函数名len,print。
3.1.2、全局名称空间:存放于文件级别的名字,顶格的名称。
3.1.3、局部名称空间:函数内部定义的名字。
3.2、名称空间的生命周期
3.2.1、内置名称空间:伴随着python解释器的启动而产生,关闭而回收。
3.2.2、全局名称空间:伴随着python文件的开始执行而产生,执行完毕而回收。
3.2.3、局部名称空间:伴随着函数的调用而产生,函数结束调用而回收。
3.3、名称空间的顺序
加载顺序:内置名称空间 > 全局名称空间 > 局部名称空间
查找顺序:局部名称空间 > 全局名称空间 > 内置名称空间
# 函数内部使用的名字,在定义阶段就已经规定死了,与你的调用位置无关
def func1(): x = 2 def func2(): x = 3 print('func2:', x) func2() print('func1:', x) func1()
四、作用域
4.1、分类
4.1.1、全局作用域
位于全局名称空间、内置名称空间中的名字属于全局范围。该范围内的名字全局存活、全局有效(在任意位置都可以使用)。
4.1.2、局部作用域
位于局部名称空间的名字属于局部范围。该范围内的名字临时存活(即在函数调用时临时生成,函数调用结束后就释放)、局部有效(只能在函数内使用)。
4.2、作用域与名字查找优先级
4.2.1、在局部作用域查找名字时,起始位置是局部作用域,所以先查找局部名称空间,没有找到,再去全局作用域查找:先查找全局名称空间,没有找到再查找内置名称空间,最后没找到抛出异常。
x = 1 def foo2(): x = 2 def foo3(): x = 3 print(x) #x=1 foo3() foo2()
4.2.2、在全局作用域查找名字时,起始位置时全局作用域,所以先查找全局名称空间,没有找到再查找内置名称空间,最后没找到抛出异常。
x = 1 def foo2(): x = 2 foo2() print(x) #1
#4.2.3、python支持函数的嵌套定义,在内嵌的函数查找名字时,会优先查找自己局部作用域的名字,然后由内而外一层层查找外部嵌套函数定义的作用域,都没有找到,则查找全局作用域。
x = 1 def foo(): x = 2 def foo1(): x = 3 def foo2(): # x = 4 def foo3(): x = 5 print('foo3:',x) #5 foo3() print('foo2:',x) #4 foo2() print('foo1:',x) #3 foo1() print(x) #2 foo()
#在函数内,无论嵌套多少层,都可以查看到全局作用域的名字,若要在函数内修改全局名称空间的名字值,需要用到global关键字
x = 1 def foo2(): global x x = 2 foo2() print(x) #2
#nonlocal x = 1 def foo2(): x = 2 def foo3(): nonlocal x x = 3 print(x) x=3 foo3() foo2()