一、装饰器(decorator)
当我们定义好一个函数的时候,还想为函数添加一些功能,但是不想改变已经函数。这个时候,我们就可以使用装饰器,为定义好的函数添加功能,且不修改函数中的代码,是非常好用的一个方法。这里要注意一下,所谓的添加功能,指的是在函数执行前或执行完后添加功能。
# 实例1,定义一个函数,输入字符串"python"
def func():
print(‘python‘)
func()
>>> python
如果我们想在字符串 "python" 前面添加另外一个字符串 "hello"
# 实例2
def add(func):
print(func.__name__)
# xxx.__name__ 代表的是取函数名称,这里是取func1的函数名称
def f():
print("hello")
# 在func1函数运行前,打印出 "hello"
func()
# 运行 func1,这里已经把 fun1赋值给变量func了
return f
# 这里是一个返回函数
@add
# 在定义函数的前一行使用python的 @ 符号,等于执行了 func1 = add(func1)
def func1():
print(‘python‘)
func1()
print(func1.__name__)
# 再一次输出 func1 的函数名称
>>> func1
hello
python
f
# 因为函数 f 作为返回函数,func1 在函数 f 中执行,所以 func1 函数赋给了 函数 f,所以,函数的名称会发生变化。
我们看看装饰器的局限性
# 实例3
def add(func):
def f1():
print(‘+ add qian mian‘)
func()
print(‘+ add hou mian‘)
return f1
@add
def f2():
print(‘zhe shi han shu de gong neng‘)
f2()
>>> + add qian mian
zhe shi han shu de gong neng
+ add hou mian
# 这个实例说明了,我们只能往函数执行前或者执行后的地方添加功能。
当我们想往附加的函数中传入参数的时候,必须另外嵌套一个函数,以此传入参数。
# 实例4
def addtext(text1,text2):
def add(func):
def f1():
print(‘+ add {0}‘.format(text1))
func()
print(‘+ add {0}‘.format(text2))
return f1
return add
@addtext(‘aaaa‘,‘bbbb‘)
def f2():
print(‘zhe shi han shu de gong neng‘)
f2()
>>> + add aaaa
zhe shi han shu de gong neng
+ add bbbb
# 当我们要传入参数值的时候,在 @函数名的后面附加一个圆括号,并带入参数。@addtext(‘aaaa‘,‘bbbb‘) 等同于 f2=addtext(‘aaaa‘,‘bbbb‘)(f2)
# f2=addtext(‘aaaa‘,‘bbbb‘)(f2) ,首先执行的是 addtext(‘aaaa‘,‘bbbb‘),然后执行 add(f2)......
我们在实例3中出现一个函数名称会变化的问题,我们该怎么解决呢?使用 functools.wraps
# 实例5
import functools
# 导入functools模块
def add(func):
print(func.__name__)
@functools.wraps(func)
def f():
print(‘addtext‘)
func()
return f
# 开始定义函数 f1
@add
def f1():
print(‘python‘)
f1()
print(f1.__name__)
# 首先导入functools函数,利用@functools.wraps(func) 来解决函数名变化的问题。切记不要使用 f.__name__=func.__name__
二、偏函数
当我们要经常使用 int 进行二进制转换为十进制的时候,会用到 print(int(‘100011‘,2)) 。但是如果每次进行转换的时候,都要对 int 的参数base赋值,这样是很麻烦。那怎么解决呢?
# 实例1
def _int(n,base=2):
return (n,base)
_int(1010101)
>>> 35
# 这是一种解决办法,重新定义一个函数。
但是,python 的模块 functools.partial 可以帮我们创建一个偏函数,省去了自定义函数的麻烦
functools.partial(函数名称,参数)
- 作用就是相当于把参数给固定了,不用每次都给赋值
# 实例2
import functools
_int=functools.partial(int,base=2)
print(_int(‘101011‘))
>>> 43
偏函数可以传入函数对象、*args和**kw这3个参数
# 实例3
import functools
s=functools.partial(max,1123)
print(s(666,22))
>>> 1123
# functools.partial(max,1123)中,1123 以参数的形式传入max函数中,并进行运算。
# 实例4
import functools
k={‘base‘:2}
_int=functools.partial(int,**k)
print(_int(‘10101‘))
# functools.partial 接收了 **kw 参数
原文:https://www.cnblogs.com/pyshadow/p/10400374.html