函数对象:
函数是第一类对象,即函数可以当做数据传递
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