柯里化Currying:柯里化指的是将原本接受两个参数的函数变成新的接受一个参数的函数过程,新的函数返回一个以原有第二参数为参数的函数 如:z = f(x, y) 转换成 z = f(x)(y)
柯里化举例:
def add(x,y):
return x+y
柯里化之后为:把两个参数的函数变为一个参数的函数
def add(x): #通过嵌套函数就可以柯里化了
def _add(y):
return x + y
return _add
add(5)(6) #返回11
---------------------------
装饰器*****:
无参装饰器定义: 是一个函数,函数作为它的形参,无参装饰器实际上就是一个单形参函数,返回也是一个函数,可以用@functionname方式简化调用(这是装饰器的语法糖),装饰器可以是告诫函数,装饰器是对传入的函数功能的装饰,可以增强或者削弱
def logger(func): #等价传入了add这个函数名
def _logger(*args,**kwargs): #将add的值接收
start = datetime.datetime.now()
ret = func(*args,**kwargs) #被*args封装成元组后 这里解构 然后把函数对象给ret
delta = (datetime.datetime.now() - start).total_seconds()
print('函数{} 执行时间为{}秒'.format(func.__name__,delta)) #打印函数名跟执行时间
return ret #这里拿到函数对象返回回去执行函数
return _logger #返回内存函数
@logger #等价 add = logger(add) 将下面的函数名当参数传入logger函数
def add(x,y): #上面返回函数时这里执行
time.sleep(1) #睡一秒钟
return x+y
print(add(3,4)) #这里调用
怎么理解装饰器呢 有个图
装饰器的文档字符串:Python文档字符串Documentation Strings
在函数语句块的第一行,且习惯是多行的文本,所以多使用三引号 惯例是 首字母大写,第一行写概述,空一行,第三行写详细描述可以使用特殊属性__doc__访问这个文档
举例:
def add(x,y):
"""This is a function of addition""" # 这就是文档字符串
a = x+y
return x + y
print("name={}\ndoc={}".format(add.__name__, add.__doc__)) #这里就是查看名字跟文档内容
print(help(add))# 调用add 查看文档内容
## 副作用 用装饰器不去写一个替换函数的话 原对象的文档属性就会被替换 用的是装饰器的文档内容
functools模块:
functools.update_wrapper(wrapper,wrapped,assigned=WRAPPER_ASSIGNMENTS, updated=WRAPPER_UPDATES) 类似copy_properties功能 wrapper包装函数、被更新者,wrapped被包装函数、数据源元组WRAPPER_ASSIGNMENTS中是要被覆盖的属性 ‘module ’, ‘name ’, ‘qualname ’, ‘doc ’, ‘annotations ’ 模块名、名称、限定名、文档、参数注解元组WRAPPER_UPDATES中是要被更新的属性,__dict__属性字典 增加一个__wrapped__属性,保留着wrapped函数
带参装饰器举例:
import datetime
import time
import functools # 导入functools 模块
下面这一段就是functools模块中wraps帮我做的事 替我copy原函数的文档字符串不被装饰器替换掉
#def copy_(src): # 把处理文档字符串copy的方法提出来
# def copy_s(dest): # 这里使用了柯里化
# dest.__name__ = src.__name__
# dest.__doc__ = src.__doc__
# return dest
# return copy_s
def logger(duration):
def _logger(wrapped): # wrapped 被包装函数就是add
# @copy_(wrapped)
@functools.wraps(wrapped) # 这里使用了functools模块里的wraps 相当于帮我做文档字符串copy
def wrapper(*args,**kwargs): # 包装函数
start = datetime.datetime.now()
ret = wrapped(*args,**kwargs)
delta = (datetime.datetime.now() - start).total_seconds()
if delta > duration: # 做一个执行时间的判断
print('too slow')
else:
print('so fast')
return ret
return wrapper
return _logger
@logger(2) # 等价 --> add = logger(2)(add) # 带了一个参数
def add(x,y):
""" I am Ironman """ ##文档字符串
time.sleep(1)
return x + y
# print(add(4,5))
print(add.__name__,add.__doc__) #调用