“专业人士笔记”系列目录:创帆云:Python成为专业人士笔记--强烈建议收藏!每日持续更新!zhuanlan.zhihu.com
介绍
使用装饰器修饰的函数是一种软件设计模式。它们动态地更改函数、方法或类的功能,而不必直接使用子类或更改被修饰函数的源代码。如果使用正确,装饰器可以成为开发过程中的强大工具。本文介绍Python中装饰函数的实现和应用
修饰函数
修饰符扩展了其他函数或方法的功能。任何将函数作为参数并返回增强函数功能目的返回的函数都可以用作修饰符
下面来一个简单的装饰函数:
#简单的修饰函数
def super_secret_function(f):
print("我装饰了你")
return f
#下面的函数使用了装饰器进行了功能增强
@super_secret_function
def my_function():
print("这是被装饰的函数")
#调用函数,我们看看会发生什么
my_function();
#输出:
我装饰了你
这是被装饰的函数
其中@符号用于声明函数的装饰器
为了理解装饰器是如何工作的,记住这一点是很重要:装饰器函数必须接受一个函数作为参数,并且返回它所装饰的函数。看看如果不返回函数会发生什么:
def disabled(f):
"""
此函数不返回任何内容,因此从本地范围中自动删除了修饰后的函数。
"""
pass
@disabled
def my_function():
print("这个被装饰的函数被调用就会报错")
my_function()
# 报错:TypeError: 'NoneType' object is not callable
因此,我们通常在装饰器中定义一个新函数并返回它。这个新函数将首先执行它需要执行的一些操作,然后调用原始函数,最后处理返回值。考虑这个简单的装饰函数,它打印原始函数接收的参数,然后调用它 :
# 这是装饰器函数
def print_args(func):
def inner_func(*args, **kwargs):
print(args)
print(kwargs)
return func(*args, **kwargs) # 调用原始函数并传递参数
return inner_func
@print_args
def multiply(num_a, num_b):
return num_a * num_b
print(multiply(3, 5))
# 输出:
# (3,5) - 这实际上是函数接收到的‘args’。
# {} - 这是'kwargs',为空,因为我们没有指定关键字参数。
# 15 - 被修饰函数的最终输出
修饰类
正如在介绍中提到的,装饰器是一个可以应用于其他函数以增强其行为的函数。但是如果装饰器是一个类呢?语法仍然可以工作,只是现在我的装饰函数被替换为装饰器类的一个实例了。如果这个类实现了__call__() 方法,那么它甚至可以像使用函数那样使用装饰器:
class Decorator(object):
""" 简单的装饰类 """
def __init__(self, func):
self.func = func
def __call__(self, *args, **kwargs):
print(' 函数调用前')
res = self.func(*args, **kwargs)
print('函数调用后.')
return res
@Decorator
def testfunc():
print('函数调用中.')
testfunc()
# 函数调用前
# 函数调用中
# 函数调用后
注意,从类型检查的角度来看,用类修饰符修饰的函数不再被认为是“函数” :
import types
class Decorator(object):
""" 简单的装饰类 """
def __init__(self, func):
self.func = func
def __call__(self, *args, **kwargs):
print(' 函数调用前')
res = self.func(*args, **kwargs)
print('函数调用后.')
return res
@Decorator
def testfunc():
print('函数调用中.')
print(isinstance(testfunc, types.FunctionType))
#输出: False
print(type(testfunc))
#输出:
修饰类方法
对于修饰方法,你需要定义一个附加的__get__方法 :
from types import MethodType
class Decorator(object):
def __init__(self, func):
self.func = func
def __call__(self, *args, **kwargs):
print('Inside the decorator.')
return self.func(*args, **kwargs)
def __get__(self, instance, cls):
# 如果在实例上调用方法,则返回该方法
return self if instance is None else MethodType(self, instance)
class Test(object):
@Decorator
def __init__(self):
pass
a = Test()
带参数的修饰器
默认情况下,修饰器只接受一个参数: 要修饰的函数。没有办法传递其它的参数
但使用中往往需要传递更多的参数。这里的技巧是创建一个函数,该函数接受任意数量的参数并返回修饰器
def decoratorfactory(message):
def decorator(func):
def wrapped_func(*args, **kwargs):
print('这个修饰器告诉你: {}'.format(message))
return func(*args, **kwargs)
return wrapped_func
return decorator
@decoratorfactory('Hello World')
def test():
pass
test()
#输出:这个修饰器告诉你: Hello World
特别注意:对于这样的装饰器,必须使用一对括号传递参数来调用装饰器 :
@decoratorfactory # 这里没有加括号
def test():
pass
test()
#会报错:TypeError: decorator() missing 1 required positional argument: 'func
好了,今天的分享就到这里,禁止转载,