python中的装饰器

查阅官方文档、大神博客等,总结如下文档。目的是备份资料,方便以后查阅温习,也希望对大家有所帮助!

环境: python3.7

一、相关理论知识

  1. python的常识,函数和其他任何东西一样,都是对象。这意味着可以将函数当做实参传递给函数,或者在函数中将函数作为返回值。
  2. 装饰器的作用是什么呢?简单的理解就是:装饰原有的函数。什么意思呢?比如有一个函数func(a, b),它的功能是求a,b的差值,我现在有一个需求,就是想对函数功能再装饰下,求完差值后再取绝对值,但是不能在func函数内部实现,这时候就需要装饰器函数了,比如func = decorate(func)函数,将func函数作为参数传递给decorate函数,由decorate来丰富func函数,丰富完成后再返回给func,此时func的功能就丰富了。
  3. 装饰器符号“@”属于语法糖,什么意思呢?就是说,我不按照@装饰器的语法要求来写,而是按照一般python的语法要求来写完全可以。那么用@装饰器的格式来写的目的就是为了书写简单方便。2. 装饰器符号“@”属于语法糖,什么意思呢?就是说,我不按照@装饰器的语法要求来写,而是按照一般python的语法要求来写完全可以。那么用@装饰器的格式来写的目的就是为了书写简单方便

二、案例(加深对装饰器的理解)

例1: 定义并应用一个装饰器(不建议使用这种方式)

def decorate1(func):            #定义一个装饰器
	def inner(a,b):
		z=func(a,b)		
		return abs(z)
	return inner

def sub(x,y):
	return x-y

sub2=decorate1(sub)        #应用装饰器decorate1
print(sub2(1,2))           #结果是1

例2: 定义并应用一个装饰器(建议使用这种方式)

def decorate1(func):
	def inner(a,b):
		z=func(a,b)		
		return abs(z)
	return inner
#个人认为,下面的3行代码的本质是:定义了一个inner函数,其中,先调用func函数z=func(a,b),然后对返回值取绝对值并返回。
@decorate1
def sub(x,y):
	return x-y    

print(sub(1,2))  #结果是1

特别说明:

1、装饰器的定义要注意3点:参数是函数;内部再定义一个函数;返回内部定义的函数
2、’’‘当我们调用sub函数时,实际上是调用经过decorate1装饰的sub函数,返回值由表面的x-y,变成了abs(x-y).’’’

例3: 定义并应用一个装饰器,同时使用封皮wraps(建议使用这种方式)

例2中定义并使用装饰器的方式存在一个问题:经过装饰后函数的__name__、doc__等变量的值也会发生变化,会变成装饰函数中内部函数的___namedoc__等的值,但我们常常有这么一种需求,经过装饰后原函数发生变化,但__name、__doc__等属性不发生变化。为解决这个问题,引入了python装饰器之@functools.wraps。

python装饰器之@functools.wraps的作用就是,不改变原函数的结构(即__name__、__doc__等)

例3-1(未使用wraps):

def logged(func):
    def with_logging(*args, **kwargs):
        """doc of with_logging"""
        print(func.__name__ + " was called")
        return func(*args, **kwargs)
    return with_logging

@logged
def f(x):
    """doc of f"""
    return x + x * x

if __name__ == '__main__':

    print(f.__name__)  # 结果是:with_logging
    print(f.__doc__)  # 结果是:doc of with_logging

例3-2(使用wraps):

import functools

def logged(func):
    @functools.wraps(func)
    def with_logging(*args, **kwargs):
        """doc of with_logging"""
        print(func.__name__ + " was called")
        return func(*args, **kwargs)
    return with_logging

@logged
def f(x):
    """doc of f"""
    return x + x * x

if __name__ == '__main__':

    print(f.__name__)  # 结果是:f
    print(f.__doc__)  # 结果是:doc of f

@functools.wraps(func)部署在with_logging函数前,可以理解为:with_logging内部函数只是装饰func,并没有改变func的本质(即没有改变__name__、__doc__等)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值