背景:由于函数也是一个对象,而且函数对象可以被赋值给变量,所以,通过变量也能调用该函数
def getnow():
print('2020-05-24')
f=getnow
print(f())
#函数对象有一个__name__属性,可以拿到函数的名字:
print(f.__name__)
但是你可能会觉得这函数太少功能,但是又不想修改函数的定义,增加一定的功能,在代码运行期间动态增加功能的方式,称之为“装饰器”。(Decorator)。本质上,decorator就是一个返回函数的高阶函数
有篇文章个人觉得讲述的很好
1:什么是装饰器:然后通过实现各种功能来对这个函数的功能进行增强。就比如,我不想在getnow里面打印出getnow这个函数的名字,我想用外部的‘函数’来打印:
2:为什么用:装饰器是通过某种方式来增强函数的功能。当然,我们可以通过很多方式来增强函数的功能,只是装饰器有一个无法替代的优势–简洁(比如我下面代码示例,我想在每个get_函数打印各自函数的名字,普通的做法可能是:写一个打印函数print(fun),参数是每个fun),但是我选择只用: @print 就行了,连参数都可以省略
3:怎么用:每个函数上方加一个@就可以对这个函数进行增强
def log(fun):#装饰器的参数 就是 一个函数
def printf():
print('call %s():',%fun.__name__)#打印出 参数函数名字
return fun()
return printf
# 我个人觉得
@log
def getnow():
print('2020-05-20')
getnow()
@log
def getlastyear():
print('2019-05-20')
getlastyear()
实质是什么? log()是一个decorator,返回一个函数,所以,原来的getnow()函数仍然存在,只是现在同名的getnow变量指向了新的函数,于是调用now()将执行新函数,即在log()函数中返回的printf函数。
2:嵌套的装饰器
def log(text):
def decorator(fun):
def wrapper():
print('%s %s()'%(text,fun.__name__))
return fun
return wrapper
return decorator
#多加了一层 引用
@log('执行')
def getnow():
print('2014-05-20')
getnow()
分析:首先执行log(‘执行’),返回的是decorator函数,再调用返回的函数,参数是fun函数,返回值最终是wrapper函数。
缺点:使用装饰器会破坏函数的一些属性
解决之道: 引入一个:functools.wraps:在定义wrapper()的前面加上@functools.wraps(func)
import functools
def log(text):
def decorator(fun):
@functools.wraps(fun)
def wrapper():
print('%s %s()'%(text,fun.__name__))
return fun
return wrapper
return decorator
#多加了一层 引用
@log('执行')
def getnow():
print('2014-05-20')
getnow()
print(getnow.__name__)
#>> 执行 getnow()
#>> getnow
偏函数
作用:偏函数的作用主要是为了修改函数的默认值
背景:我们要把数字字符串转换成真的数字我们通常:
str2int=int('9876')
#或者是:
str2int16=int('9876',base=16)#16转换成10进制
#但假如是转换非常多的数据怎么办 我们可能会想到搞一个函数来实现
def str2int(x,base=2):
return int(x,base)
blackwidom=str2int('1010')
即使是这样,那些开发python的大佬们也觉得不够简洁。于是:
import functools
int2=functools.partial(int,base=2)
#实例化
num=int2('101010100010')
#>>2722 结果
functools.partial(参数1,参数2),就是帮助我们创建一个偏函数的,实质是:把一个函数的某些参数给固定住(也就是设置默认值),返回一个新的函数,调用这个新函数会更简单。就是对内部函数再改造,返回值是一个函数。参数1是一个函数名儿。
但是如果你的参数2是一个数字,
import functools
mmax=functools.partial(max,9)
#实例化
mmax(1,2,4)
#就相当于:
max(9,1,2,4)