函数对象
- 函数对象指的是函数可以被当做’数据’来处理,具体可以分为四个方面的使用
函数可以被引用
def add(x, y):
return x + y
func = add
func(1, 2) # 3
函数可以作为容器类型的元素
>>> def add(x,y):
... return x+y
...
>>> func=add
>>> func(1,2)
3
函数可以作为参数传入另外一个函数
>>> dic={'add':add,'max':max}
>>> dic
{'add': <function add at 0x100661e18>, 'max': <built-in function max>}
>>> dic['add'](1,2)
3
函数的返回值可以是一个函数
>>> def foo(x,y,func):
... return func(x,y)
...
>>> foo(1,2,add)
3
闭包函数
闭包函数简介
- 闭包函数:在一个内部函数中,对外部作用域的变量进行引用,(并且一般外部函数的返回值为内部函数),那么内部函数就被认为是闭包
- 定义在函数内部的函数
- 内部函数使用了外部函数
def func():
username = 'jason'
def index():
print(username)
return index
res = func()
print(res)
res() # jason
def func(username):
def index():
print(username)
return index
func('jason')
闭包函数实际应用
# 给函数体代码传值的方式一:通过形参传值
def func(xxx):
print(xxx)
# 给函数体代码传值的方式2:闭包函数
def index():
username = 'jason'
def func():
print(username)
return func
res = index('jason')
res()
装饰器
装饰器简介
- 装饰器:函数知识整合到一块的产物
- 装饰器本质:在不改变装饰对象原来的‘调用方式’和‘内部代码’的情况下给被装饰的对象添加功能
- 装饰器原则:对修改封闭,对扩展开放
- 知识储备
import time
print(time.time()) # 1656987566.7260265
# 时间戳(秒数):当前距离1970年1月1日0时0分0秒所经历的秒数
# 实际应用:统计代码的运行时间
start_time = time.time() # 100
for i in range(100000):
print(i)
end_time = time.time()
print('for循环的执行时间是: %s '%(end_time - start_time))
time.sleep(3) # 让程序等待三秒
print('睡不醒,我好困')
装饰器前期推导
import time
def index():
time.sleep(3)
print('from index')
# 统计index函数的执行时间
start_time = time.time() # 在调用index函数之前获取一下时间戳
index() # 调用index函数
end_time = time.time()
print(end_time - start_time)
- 缺陷:如果有多个index需要统计时间,则需要重新编码
- 解决措施:封装成函数
import time
def index():
time.sleep(3)
print('from index')
def get_time():
start_time = time.time() # 在调用index函数之前获取一下时间戳
index() # 调用index函数
end_time = time.time()
print('函数的执行时间是:', end_time - start_time)
get_time()
- 缺陷:如果有多个不同的函数需要统计时间 那么上述的解决措施不够完善
- 解决措施:给函数体添加形参(动态传参)
import time
def index():
time.sleep(3)
print('from index')
def home():
time.sleep(5)
print('from home')
def get_time(xxx):
start_time = time.time() # 在调用index函数之前获取一下时间戳
xxx(*args, **kwargs) # 调用index函数
end_time = time.time()
print('函数的执行时间是:', end_time - start_time)
get_time(index)
get_time(home)
- 缺陷:不同形参个数的函数无法兼容统计
- 解决措施:*args ** kwargs,目前的代码中无法实现(暂且忽略)
import time
def func1(a):
time.sleep(1)
print('from func1')
get_time(func1)
- 缺陷:改变了原来的调用方式
- 解决措施:装饰器推导流程
装饰器各种版本
import time
"""针对有参无参函数如何兼容"""
def outer(xxx):
def get_time(*args, **kwargs):
start_time = time.time() # 在调用index函数之前获取一下时间戳
res = xxx(*args, **kwargs) # 调用index函数
end_time = time.time()
print('函数的执行时间是:', end_time - start_time)
return res
return get_time
def home():
time.sleep(2)
print('from home')
return '执行home函数之后的返回值'
def index(name):
time.sleep(1)
print('from index')
return '执行index函数之后的返回值'
home = outer(home)
xxx = home()
print(xxx)
index = outer(index)
res = index('jason')
print(res)
home = outer(home)
home()
def func(a, b, c):
time.sleep(1)
print('from func')
index = outer(index)
index('jason')
home = outer(home)
home()
func = outer(func)
func(1, 2, 3)
装饰器的固定模板
from functools import wraps
def outer(func_name):
@wraps(func_name) # 仅仅是为了让装饰器不容易被别人发现 做到真正的以假乱真
def inner(*args, **kwargs):
print('执行被装饰对象之前可以做的额外操作')
res = func_name(*args, **kwargs)
print('执行被装饰对象之后可以做的额外操作')
return res
return inner
import time
def home():
time.sleep(1)
print('from home')
return 'home返回值'
home = outer(home)
res = home()
print(res)
import time
@outer # home = outer(真正的函数名home)
def home():
'''我是home函数 我要热死了!!!'''
time.sleep(1)
print('from home')
return 'home返回值'
help(home)
print(home)
home()
def index():
'我是index函数 我的功能很强大'
pass
help(index)