函数对象与闭包
目录
一、函数对象
函数对象指的是函数可以被当做‘数据’来处理,
函数名不加括号就是指函数的内存地址
函数名加括号,就是调用函数,找到函数体代码并执行,不论在哪个位置
def index():
print('from index')
print(index) # <function index at 0x0000016EE3462F28>
具体可以分为四个方面的使用,我们如下
1.1 函数名可以当成变量赋值
def index():
print('from index')
a = index
a() # => index(),也可以调用函数
print(a) # <function index at 0x0000013E4FA92F28>
1.2 函数名可以当成函数的实参
# 2.1 只打印a
def index():
print('from index')
def func(a):
print(a) # a => index
print('from func')
func(index)
# 输出结果是:
# <function index at 0x0000021506D82F28>
# from func
# 2.2 运行了a()
def index():
print('from index')
def func(a):
print(a) # a => index
a()
print('from func')
func(index)
# 输出结果是:
# <function index at 0x0000024D40F12F28>
# from index
# from func
# 2.3 错误
def index():
print('from index')
def func(a):
a()
print('from func')
# 将函数的返回值当成了参数,但是index的返回值是空,会报错
# func(index()) # 填入的是None,不能运行,会报错
1.3 函数名可以当成函数的返回值
def index():
print('from index')
def func():
print('from func')
return index # 返回的就是index函数的内存地址
res=func() # res就是index函数的内存地址
print(res)
res()
# 输出结果是:
# from func
# <function index at 0x0000017630372F28>
# from index
1.4 函数名可以当成容器类型的元素
def index():
print('from index')
return 'from a'
l = [11, 22, 33, index] # 函数index并没有调用,不会返回'from index'
print(l)
l1 = [11, 22, 33, index()] # index()出现,函数被调用
print(l1)
# 输出结果是:
# [11, 22, 33, <function index at 0x000002187F9B2F28>]
# from index
# [11, 22, 33, 'from a']
1.5 小练习:优化登录注册功能
用之前所学知识写出:
def register():
print('注册')
def login():
print('登录')
def transfer():
print('转账')
def shopping():
print('购物')
def withdraw():
print('提现')
while True:
print("""
1. 注册
2. 登录
3. 转账
4. 购物
5. 提现
""")
choice = input('请输入编号:').strip()
if choice == '1':
register()
elif choice == '2':
login()
elif choice == '3':
transfer()
elif choice == '4':
shopping()
else:
print('没有改功能')
这种方式比较繁琐,这是只有5个功能,如果有50个功能,用这种方式更加繁琐,或者想要增加一个功能需要改变的步骤太多。
以下是用新方法改的代码:
直接使用字典,将函数名与序号组成键值对形式写入字典中。
'''函数名只要加括号,就会执行!!!!!!!!!'''
def register():
print('注册')
def login():
print('登录')
def transfer():
print('转账')
def shopping():
print('购物')
def withdraw():
print('提现')
def chongzhi():
print('cz')
func_dict = {
'1': register,
'2': login,
'3': transfer,
'4': shopping,
'5': withdraw,
'6': chongzhi,
}
while True:
print("""
1. 注册
2. 登录
3. 转账
4. 购物
5. 提现
6. 充值
""")
choice = input('请输入编号:').strip()
# 判断用户输入的编号在不在fund_dict这个字典里面
if choice in func_dict:
func_name = func_dict.get(choice) # 函数的内存地址
func_name()
# 上面两行代码可以简写
# func_dict.get(choice)()
else:
print('不存在')
二、函数的嵌套调用
2.1 在函数内部定义函数
def index():
print('from index')
print('111')
print('222')
print('333')
def func():
index()
print('from func')
func()
# 输出结果是:
# from index
# 111
# 222
# 333
# from func
练习1:判断两个数的大小
判断两个数的大小
有两种不同的写法:
写法1:
def my_max(a, b):
if a > b:
return a
else:
return b
res = my_max(2, 3)
print(res) # 3
写法2:
这种方法更高级一点
def my_max(a, b):
if a > b:
return a
return b
res = my_max(70, 5)
print(res) # 70
练习2:判断4个数的大小
判断4个数的大小,返回大的
# 2.1 先写出一个函数判断两个数的大小
def my_max(a, b):
if a > b:
return a
return b
def many_max(a, b, c, d):
res = my_max(a, b) # b
res1 = my_max(res, c)
res2 = my_max(res1, d)
return res2
ret = many_max(1, 2, 3, 4)
print(ret)
2.2 函数嵌套
# 把复杂的功能隐藏起来,暴露给外界一个简单的接口
def all_func(type):
def register():
pass
def login():
pass
def shopping():
pass
def transfer():
pass
if type == '1':
register()
elif type == '2':
login()
elif type == '3':
shopping()
elif type == '4':
transfer()
else:
print('不存在')
print('''
1.登录
2.注册
3.购物
4.转账
''')
choice = input('请输入你选择的序号:>>>')
all_func(choice)
# 当输入1时,就会执行注册功能,输入2时,就会执行登录功能...
二、闭包函数
闭:定义在函数内部的函数
包:内部函数使用外部函数名称空间中的名字
'''只有同时满足以上两个条件的函数,才是闭包函数'''
2.1 概念
# 1.函数变量定义在外面,func不是闭包函数,它符合闭不符合包
x = 100
def index():
def func():
print(x)
return func
index()
print(index()) # <function index.<locals>.func at 0x000002683136ED08>
# 2.是闭包函数
def index():
x = 100
def func():
print(x)
return func
index()
print(index()) # <function index.<locals>.func at 0x000002683136ED08>
2.2 作用
闭包函数的作用就是:第二种传参的方式
# 方式一:
# 传统传参
def index(username):
print(username)
def my_max(a, b):
if a > b:
return a
return b
以下是用一个案例写出闭包函数的推导流程
# 方式二:
# 使用闭包函数实现比较两个数的大小
# 写闭包函数的推导流程
# 1.
def func():
def my_max(a, b):
if a > b:
return a
return b
return my_max
res = func() # my_max的内存地址
ret = res(2, 3) # =>my_max()
print(ret)
# 这种不是闭包函数,功能可以实现,但是想要得到最后结果,还需要在内部函数my_max函数中,传入参数,比较麻烦
# 2.
def func():
a = 1
b = 10
def my_max():
if a > b:
return a
return b
return my_max
res = func() # my_max的内存地址
print(res())
# 这种是闭包函数,但此时func函数只能实现1和10的大小比较关系,所以要把a, b写活
# 3.
def func(a, b):
def my_max():
if a > b:
return a
return b
return my_max
res = func(1, 10) # my_max的内存地址
print(res())
# 这种是闭包函数,并且可以实现任何两个数大小的比较
2.3 实际应用
'''爬虫的知识'''
# 要先安装requests包
import requests
def func(url):
# url = 'http://www.baidu.com'
def get_content():
# url = 'http://www.jd.com'
# res=requests.get('http://www.baidu.com')
res=requests.get(url)
if res.status_code == 200:
with open(r'aaa.html', 'wb') as f:
f.write(res.content)
return get_content
# res=func() # get_content
# res('http://www.jd.com')
res=func("http://www.jd.com")
res()
res()
res() # 可以简单的多次调用
res1=func("http://www.baidu.com")
res1()
res1()
res1()