python3之装饰器(类装饰器)实现 下篇

上篇中我们介绍了闭包的用法,同时利用装饰器实现了为函数添加返回原始数据的功能,那么它是如何实现的呢,让我们一起来揭开它神秘的面纱。

def decorator(f):
    def wrapper(x,y):
        print("参数1为:%s,参数2为:%s"%(x,y))
        return f(x,y)
    return wrapper
    
@decorator
def add(x,y):
    return x+y

print(add(2,3))

解析:本质上装饰器就是一个返回函数的高阶函数,它接收一个函数,并返回一个函数,用法就是在被装饰的函数上面加上@装饰器函数名。此时,把@decorator 放到add函数的定义处,相当于执行了 add = decorator(add),结果就是返回了一个函数对象wrapper,wrapper后加上(x,y),然后执行装饰器函数内部定义的wrapper()函数。此时函数的指向发生了变化,让我们看下面的代码:

def decorator(f):
    def wrapper(x,y):
        print("参数1为:%s,参数2为:%s"%(x,y),f.__name__)
        return f(x,y)
    return wrapper

@decorator
def add(x,y):
    print(add.__name__)
    return x+y

print(add(2,3))

执行结果:

参数1为:2,参数2为:3 add
wrapper
5

解析:在add函数前加上@decorator,执行了decorator(add)函数,add代表传入的形参f,返回的wrapper指向了原有的add位置,新的add函数名字发生了改变。所以,我们可以使用python的functools模块把原始函数的__name__等属性复制到wrapper()函数中,否则,有些依赖函数签名的代码执行就会出错。在这之上我们还可以再添加一个函数,输出一些参数。

import functools

def log(text):
    def decorator(f):
        @functools.wraps(f)
        def wrapper(x,y):
            print(text,"参数1为:%s,参数2为:%s"%(x,y),f.__name__)
            return f(x,y)
        return wrapper
    return decorator

@log("python之装饰器")
def add(x,y):
    print(add.__name__)
    return x+y

print(add(2,3))

执行结果:

python之装饰器 参数1为:2,参数2为:3 add
add
5

解析:加上@functools.wraps(f)后,新的add()函数的名字还是原来的add,我们添加了log函数,传入了一串字符,函数执行时可以打印出来。

总结:装饰器能够将一个函数的功能在不修改代码的情况下进行扩展,在函数定义的上方@装饰器函数名 即可直接使用装饰器对下面的函数进行装饰。

类装饰器
接下来我们用面对对象的方法实现装饰器的功能,你应该有python面对对象编程的基础,这里面会用到魔法方法。
<1>

class Decrator(object):

    def __init__(self,fn):
        print("初始化函数",fn.__name__)
        self._func = fn

    def __call__(self,*args):
        print("打印的内容",*args)
        return self._func(*args)

@Decrator
def sum(x,y):
    print(sum)
    return x+y

print(sum(3,3))

执行结果

初始化函数 sum
打印的内容 3 3
<__main__.Decrator object at 0x0000024986FF7198>
6

解析:函数sum定义前加上@Decorator,相当于实例化类对象Decorator(sum),同时初始化实例属性self._func=sum函数;接下来实例对象后加上(),会调用实例对象的__call__方法,打印出内容和参数,然后返回实例属性即sum函数并执行函数计算x+y。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值