第二模块第14章 函数对象和闭包
egon老师知乎:
https://zhuanlan.zhihu.com/p/109056932
内容概要:
1. 函数对象(可以把函数当成变量去用)
2. 函数嵌套
3. 闭包函数 = 名称空间与作用域 + 函数嵌套 + 函数对象
核心点: 名字的查找关系是以函数定义阶段为准的
一 函数对象
函数对象的精髓: 可以把函数当成变量去用
1. 可以赋值
2. 可以当作参数传给另外一个函数
3. 可以当作另外一个函数的返回值
4. 可以当成容器类型的一个元素
# 应用示例 def login(): ... def transfer(): ... def check(): ... def withdraw(): ... dic = {'1':login, '2':transfer, '3':check, '4':withdraw} while True: print(''' 0 退出 1 登录 2 转账 3 查询 4 取款 ''') choice = input('请输入命令编号:') if not choice.isdigit(): print('输入有误, 请输入编号') continue if choice == '0': break if choice in dic: dic[choice]() else: print('输入的指令不存在, 请重新输入') continue
# 优化版 def login(): print('登录') def transfer(): print('转账') def check(): print('查询') def withdraw(): print('取款') dic = { '0':('退出', None), '1':('登录',login), '2':('转账',transfer), '3':('查询',check), '4':('取款',withdraw)} while True: for k,v in dic.items(): print(k,v[0]) choice = input('请输入命令编号:') if not choice.isdigit(): print('输入有误, 请输入编号') continue if choice == '0': break if choice in dic: dic[choice][1]() else: print('输入的指令不存在, 请重新输入')
二 函数嵌套
1. 函数的嵌套调用
在调用一个函数的过程中又调用其他函数
# 示例: def max2(x,y): if x > y: return x else: return y def max4(a, b, c, d): res1 = max2(a, b) res2 = max2(res1, c) res3 = max2(res2, d) return res3 res = max4(2, 0, 8, 1) print(res) # 结果: 8
2. 函数的嵌套定义
在函数内定义函数
不是很常用, 最常用于闭包函数
def f1(): def f2(): pass ''' 如果f2供所有人使用, 应该放在全局, 如果只供f1用, 则应放在f1内. '''
三 闭包函数
1. 闭包函数 = 名称空间与作用域 + 函数嵌套 + 函数对象
核心点: 名字的查找以函数定义阶段为准
2. 什么是闭包函数
'闭'函数指的是该函数是内嵌函数
'包'函数指的是该函数包含对外层函数作用域名字的引用(不是对全局作用域), 不管是对第几层函数作用域中名字的应用, 都叫包函数, 只要不是从自己所在的作用域找就行.
def f1(): x = 11111 def f2(): print(x) return f2 f2 = f1()
f2()
3. 为何要有闭包函数, 闭包函数的应用
有了两种为函数传参的方式
方式一: 直接把函数体需要的参数定义成形参
def f(x): print(x) f(1)
方式二: 闭包传参
import requests # 传参的方案一 def get(url): response = requests.get(url) print(len(response.text)) get('https://www.baidu.com') # 传参的方案二 def outer(url): # 传参相当于 url = 'https://www.baidu.com' def get(): response = requests.get(url) print(len(response.text)) return get get = outer('https://www.baidu.com') get()
egon老师知乎课件:
https://zhuanlan.zhihu.com/p/109056932
目录:
一 函数对象
1.1 函数可以被引用
1.2 函数可以作为容器类型的元素
1.3 函数可以作为参数传入另外一个函数
1.4 函数的返回值可以是一个函数
二 闭包函数
2.1 闭与包
2.2 闭包的用途
函数对象指的是函数可以被当做’数据’来处理,具体可以分为四个方面的使用,我们如下
1.1 函数可以被引用
>>> def add(x,y): ... return x+y ... >>> func=add >>> func(1,2) 3
1.2 函数可以作为容器类型的元素
>>> dic={'add':add,'max':max}
>>> dic
{'add': <function add at 0x100661e18>, 'max': <built-in function max>}
>>> dic['add'](1,2)
3
1.3 函数可以作为参数传入另外一个函数
>>> def foo(x,y,func): ... return func(x,y) ... >>> foo(1,2,add) 3
1.4 函数的返回值可以是一个函数
def bar(): return add func=bar() func(1,2) 3
二 闭包函数
2.1 闭与包
基于函数对象的概念,可以将函数返回到任意位置去调用,但作用域的关系是在定义完函数时就已经被确定了的,与函数的调用位置无关。
x=1 def f1(): def f2(): print(x) return f2 def f3(): x=3 f2=f1() #调用f1()返回函数f2 f2() #需要按照函数定义时的作用关系去执行,与调用位置无关 f3() #结果为1
也就是说函数被当做数据处理时,始终以自带的作用域为准。若内嵌函数包含对外部函数作用域(而非全局作用域)中变量的引用,那么该’内嵌函数’就是闭包函数,简称闭包(Closures)
x=1 def outer(): x=2 def inner(): print(x) return inner func=outer() func() # 结果为2
可以通过函数的closure属性,查看到闭包函数所包裹的外部变量
>>> func.__closure__ (<cell at 0x10212af78: int object at 0x10028cca0>,) >>> func.__closure__[0].cell_contents 2
“闭”代表函数是内部的,“包”代表函数外’包裹’着对外层作用域的引用。因而无论在何处调用闭包函数,使用的仍然是包裹在其外层的变量。
2.2 闭包的用途
目前为止,我们得到了两种为函数体传值的方式,一种是直接将值以参数的形式传入,另外一种就是将值包给函数
import requests #方式一: def get(url): return requests.get(url).text #方式二: def page(url): def get(): return requests.get(url).text return get
提示:requests模块是用来模拟浏览器向网站发送请求并将页面内容下载到本地,需要事先安装:pip3 install requests
对比两种方式,方式一在下载同一页面时需要重复传入url,而方式二只需要传一次值,就会得到一个包含指定url的闭包函数,以后调用该闭包函数无需再传url
# 方式一下载同一页面 get('https://www.python.org') get('https://www.python.org') get('https://www.python.org') …… # 方式二下载同一页面 python=page('https://www.python.org') python() python() python() ……
闭包函数的这种特性有时又称为惰性计算。使用将值包给函数的方式,在接下来的装饰器中也将大有用处
浙公网安备 33010602011771号