函数对象
一、函数是第一类对象(即函数可以当作数据传递),函数是第一等公民
#1 可以被赋值
# def foo(): # foo->函数的内存地址
# print('from foo')
# f=foo 将foo的内存地址赋值给f
# print(f)
#f()
#2 可以当作参数传给另一个函数
# def foo(): # foo->函数的内存地址
# print('from foo')
# def func(f):
# print(f)
# f()
# func(foo)
#3 返回值可以是函数
# def foo(): # foo->函数的内存地址
# print('from foo')
# def func(f):
# return f
# res=func(foo)
# print(res)
#4 可以当作容器类型的元素
# def foo(): # foo->函数的内存地址
# print('from foo')
# l = [foo]
# 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]()
函数嵌套
1、函数的嵌套调用:在调用一个函数的过程中,该函数内部又调用了其他函数
def max(x,y):
if x > y:
return x
else:
return y
def max4(a,b,c,d):
res1=max(a,b)
res2=max(res1,c)
res3=max(res2,d)
return res3
print(res)
max4(1,2,3,4)
2、函数的嵌套定义:在函数内又定义了其他函数-------->封闭
def f1():
def f2():
def f3():
print('from f3')
f3()
f2()
f1()
名称空间与作用域
1、 名称空间Namespace: 存放名字与内存地址绑定关系的地方
内置名称空间:放的是python自带的名字,print\len\input
生命周期:解释器启动则产生,解释器关闭则销毁
全局名称空间:放的是顶级的名字,如下x\y\foo
生命周期:运行python文件则立即产生,python文件运行完毕则结束
局部名称空间:放的是函数内的名字,如上z
生命周期:调用函数则产生,函数调用完毕则销毁
重要结论1: 名字的查找优先级
局部-》全局-》内置
基于自己当前所在的位置向外查找,LEGB
重要结论2: 名称空间的嵌套关系是以函数定义为准生成的,与调用位置无关
2、作用域
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 内置模块的名字空间
global与nonlocal关键字
global关键字 将全局变量拿来局部用
x=111
def foo():
global x
x=222
foo()
print(x)
nonlocal关键字: 声明一个名字是来自于外层函数,如果外层没有不会找到全局,会报错
x = 1
def f1():
x = 2 # 将x=2注销,在函数内找不到x,运行程序会报错
def f2():
nonlocal x
x = 3
f2()
print(x)
f1()
闭包函数
什么是闭包函数
闭包函数=函数对象+函数嵌套定义+名称空间与作用域
闭函数:定义在函数内部的函数
包函数: 内部函数引用了一个外层函数的名字
内部函数包含对外部作用域而非全局作用域的引用
之前我们都是通过参数将外部的值传给函数,闭包提供了另外一种思路,包起来
闭包的函数的作用:闭包函数是一种为函数体传参的方案
为函数体传参方案一:直接使用形参
def wrapper(x):
print(x)
wrapper(111)
wrapper(222)
wrapper(333)
为函数体传参方案二:闭包函数
def outter(x):
# x = 111 #写x=111,就把写死了
def wrapper():
print(x)
return wrapper
wrapper = outter(111)
wrapper()
wrapper = outter(222)
wrapper()
闭包函数的意义与应用
闭包的意义:返回的函数对象,不仅仅是一个函数对象,在该函数外还包裹了一层作用域,这使得,该函数无论在何处调用,优先使用自己外层包裹的作用域
应用领域:延迟计算(原来我们是传参,现在我们是包起来)
from urllib.request import urlopen
def index(url):
def get():
return urlopen(url).read()
return get
baidu=index('http://www.baidu.com')
print(baidu().decode('utf-8'))