函数对象:
函数对象指的是函数可以被当作数据来处理,具体分为四个方面的使用:
1.函数的引用
def index(): print('fuck') a = index a()
2.函数可以当作参数传递
def add(x,y): return x + y def foo(x,y,add): return add(x,y) foo(1,2,add) print(foo(1,2,add))
3.函数的返回值可以是一个函数
def bar(): return add func = bar() func(2,3) print(func(2,3))
4.函数名可以当作容器类型的元素
def index(): print('fuck') l1 = [1,2,index,index()] f = l1[2]
函数的嵌套
在函数内调用函数
def index(): print('hello') def func(): index() print('nmh') func() >>>hello nmh
def index(): def home(): print('hello') home() index() >>hello
比较大小
def func1(x,y): if x>y: return x else: return y def func2(a,b,c,d): result = func1(a,b) result = func1(result,c) result = func1(result,d) return result print(func2(123,321,53,1)) >>321
名称空间:
存放名字的空间,如变量名,函数名
在程序执行期间最多会存在三种名称空间:
1.内置名称空间:python解释器提前定义完的名字,在解释器开启时生效,关闭时回收
2.全局名称空间:存放于文件级别的名字,启动py文件时生效,当前页面代码执行结束后失效
if,while,for内部定义的名字执行之后都存放于全局名称空间。
3.局部名称空间:函数内部定义的名字,当调用当前函数时生效,函数体代码执行结束失效
x = 10 # 全局名称空间 def f1(): x = 20 # 局部名称空间 def f2(): print('from f1',x) f2() f1() print('from file.py',x)
名称空间的查找顺序:
局部:局部 ===》全局===》内置
全局:全局 ===》内置 #内置找不到,报错
函数内部使用的名字,在定义阶段已经定死了,与你的调用位置无关
x = 1 def inner(): x = 2 def wrapper(): print(x) #在局部找x wrapper() x = 111 inner() #结果为2
print(x) #在全局查找,结果为111
练习
x = 1 def index(arg = x): print(x) print(arg) x = 2 index() >>2 1
作用域:
分类:1.全局作用域:位于全局名称空间、内置名称空间中的名字属于全局范围,该范围内的名字全局存活(除非删除)、全局有效(任何位置可用);
2.局部作用域:位于局部名称空间中的名字属于局部范围。该范围内的名字临时存活(在函数调用时临时生成,结束后释放)、局部有效(只能在函数内使用)。
名字查找的优先级: 在全局作用域查找名字时,起始位置是全局作用域,先查全面名称空间,再找内置名称空间,都没有会抛出异常。
在局部作用域查找名字时,起始位置时局部作用域,先查找局部名称空间,再去全局作用域查找:全局名称空间》》内置名称空间, 都找不到会抛出异常。
在内嵌的函数查找名字时,会优先查找自己局部作用域的名字,然后由内而外一层层查找外部嵌套函数定义的作用域,没有找到,则查找全局作用域
x = 1 def outer(): x = 2 def inner(): x =3 print('inner x:%s' %x) inner() print('outer x:%s' %x) outer() 结果为:inner x:3 outer x:2
在函数内,无论嵌套多少层,都可以看到全局作用域的名字,若要在函数内修改全局名称空间中名字的值,当值为不可变类型时,需要用到global
global
x = 1 def foo(): global x #声明x为全局变量 x = 2 foo() print(x) >>2
当实参的值为可变类型时,函数体内对该值的修改会直接反应到原值
l1 = [1,2,3] def index(a): l1.append(a) print(l1) index(5) >>[1,2,3,5]
对于嵌套多层的函数,使用nonlocal可以将名字声明为来自外部嵌套函数定义的作用域(非全局)
def f1(): x = 2 def f2(): nonlocal x x = 3 f2() #调用f2(),修改f1作用域中名字x的值 print(x) # 在f1作用域查看x f1() >>3
nonlocal x会从当前函数的外层函数开始一层层去查找名字x,若是一直到最外层都找不到,则会抛出异常。