欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

装饰器

程序员文章站 2022-06-30 14:18:23
...

所谓装饰器从字面理解就是,给一个对象添加一些东西。

类似与加工厂的作用,对象进入到一个工厂中,工厂对,"对象“进行处理加工,给“对象”加入新的功能,后输出经过加工后的“对象”。

例:

def use_logging(func):
    def wrapper():
        logging.warn("%s is running" % func.__name__)
        return func()   # 把 foo 当做参数传递进来时,执行func()就相当于执行foo()
    return wrapper
def foo():
    print('i am foo')
foo = use_logging(foo)  # 因为装饰器 use_logging(foo) 返回的时函数对象 wrapper,这条语句相当于  foo = wrapper
foo()                   # 执行foo()就相当于执行 wrapper()

装饰器

foo = use_logging(foo)  
foo() 

这太麻烦,我们还可以让写法更简便"语法糖@"
我们可以这样写

def use_logging(func):
    def wrapper():
        logging.warn("%s is running" % func.__name__)
        return func() 
    return wrapper
@use_logging
def foo():
    print('i am foo')
#foo = use_logging(foo) 
foo() 

@ 符号就是装饰器的语法糖,它放在函数开始定义的地方,这样就可以省略最后一步再次赋值的操作。

>>> def use_logging(func):
	def wrapper():
		print("%s is running"% func.__name__)
		return func()
	return wrapper
>>> @use_logging   #运行实例@use_logging要写在需要修饰对象的前边
def foo():
	print("i am foo")
>>> foo()
foo is running
i am foo
>>> def

@use_logging表示将要修饰下边所定义的对象

填加参数的方式:

def use_logging(func):
	def wrapper(name):
		print("%s is running"% func.__name__)
		return func(name)
	return wrapper
    
@use_logging
def foo(name):
	print("hello %s i am foo"% name)

直接将参数传给wrapper就可以了,不过不要忘记返回的func是需要带参数的。

实际上我们还可以让装饰器更加的灵活

def use_logging(level):
    def decorator(func):
        def wrapper(*args, **kwargs):
            if level == "warn":
                logging.warn("%s is running" % func.__name__)
            elif level == "info":
                logging.info("%s is running" % func.__name__)
            return func(*args)
        return wrapper
    return decorator
@use_logging(level="warn")
def foo(name='foo'):
    print("i am %s" % name)
foo()

上面的 use_logging 是允许带参数的装饰器。它实际上是对原有装饰器的一个函数封装,并返回一个装饰器。我们可以将它理解为一个含有参数的闭包。当我 们使用@use_logging(level=“warn”)调用的时候,Python 能够发现这一层的封装,并把参数传递到装饰器的环境中。
@use_logging(level=“warn”) 等价于 @decorator