python:装饰器

装饰器相关

对于函数:

import time


def test1():
    time.sleep(0.5)
    print('test---1')


if __name__ == '__main__':
test1()

此时想要增加一个运行计时功能,可以:

def test1():
    start_time = time.time()
    time.sleep(0.5)
    print('test---1')
    print('消耗时间:', time.time() - start_time)


if __name__ == '__main__':
    test1()

这样写改变了代码原来的结构,对于完成度比较高的代码,如果需要增加功能,尽量不要改变它的结构。

想要在不改变原来的函数结构情况下增加功能,就可以使用装饰器:

import time


def decorator(func):
    def wapper():
        start_time = time.time()
        func()
        print('消耗时间:', time.time() - start_time)

    return wapper


@decorator
def test1():
    time.sleep(0.5)
    print('test---1')


@decorator
def test2():
    time.sleep(0.5)
    print('test---2')


if __name__ == '__main__':
    test1()
    test2()

当函数比较多就可以看出装饰器的方便,还节省了代码量

执行test1()时,相当于执行了 decorator(test1)

关于装饰器的执行:

def fun_out(fun):
    def fun_in():
        print('decorator')
        fun()

    print(id(fun_in))
    return fun_in


@fun_out
def fun_1():
    print('fun_1')


fun_1()
fun_out(None)
print('fun_1函数id:', id(fun_1), '    fun_1函数名:', fun_1.__name__)
'''
@fun_out相当于执行下面的操作
fun_1 = fun_out(fun = fun_1)         相当于赋值操作,fun_1 指向了fun_out(),()代表执行,所以下面的函数会执行
            def fun_in():            在这里定义了fun_in,定义但不执行,此时fun_1 仍然 = print('fun_1)
                print('decorator')
                fun = fun_1()        print('fun_1)
        
            return fun_in            执行完毕,返回了fun_in,即fun_1 = fun_in,此时fun_1已经不是原来的print('fun_1')
      = fun_in                       fun_1 = fun_in,fun_1不是原来的  print('fun_1')
      
      
调用  
fun_1() = fun_in() = print('decorator')
                     print('fun_1)
                

'''

多重装饰器

def makeBold(fn):
    # def wrapped():
    #     return "<b>" + fn() + "</b>"
        # fn()执行ruturn,ruturn 执行过之后,wrapped 在makeBold 函数里面意为字符串"<b>" + fn() + "</b>"
    # return wrapped
    return lambda: ("<b>" + fn() + "</b>")


def makeItalic(fn):
    return lambda: ("<i>" + fn() + "</i>")


@makeBold
def test1():
    return "test-1"


@makeItalic
def test2():
    return "test-2"


@makeBold
# @makeBold发现下面不是一个函数,暂停执行
@makeItalic
# @makeItalic发现下面是test3(),执行
def test3():
    return "test-3"


print(test1())
print(test2())
print(test3())
print((lambda: 50 * '-')())

装饰类方法

import time


def decorator(func):

    def wapper():
        start_time = time.time()
        func()
        print(time.time() - start_time)

    return wapper


class MyObj(object):
    def __init__(self, content):
        self.content = content

    @decorator
    def run(self):
        time.sleep(0.5)
        print(self.content)


if __name__ == '__main__':
    obj = MyObj('你好')
    obj.run()

此时会报错误:wapper() takes 0 positional arguments but 1 was given,也就是说wapper() 传入了一个参数,原因:对于类方法,会默认传入一个self,表示实例对象,也就是说decorator(func)(self)

def decorator(func):
    def wapper(self):
        start_time = time.time()
        self()
        print(time.time() - start_time)

    return wapper


class MyObj(object):
    def __init__(self, content):
        self.content = content

    @decorator
    def run(self):
        time.sleep(0.5)
        print(self.content)
	
	# __call__() 把对象转为可执行
    def __call__(self, *args, **kwargs):
        print('call-------------')


if __name__ == '__main__':
    obj = MyObj('你好')
    obj.run()

运行结果

call-------------
0.0

可见执行了__call__(),所以装饰类方法应该:

def decorator(func):

    def wapper(self):
        # 对于类方法,会默认传入一个self,表示实例对象,也就是说decorator(func)(self),这一点可以使用下面的decorator 验证。
        start_time = time.time()
        func(self)
        print(time.time() - start_time)

    return wapper


class MyObj(object):
    def __init__(self, content):
        self.content = content

    @decorator
    def run(self):
        time.sleep(0.5)
        print(self.content)
	
	# __call__() 把对象转为可执行
    def __call__(self, *args, **kwargs):
        print('call-------------')


if __name__ == '__main__':
    obj = MyObj('你好')
    obj.run()

类装饰器

import time


class Decoretor(object):
    def __init__(self, func):
		print('Decoretor---------')
        self.func = func

	# __call__()是一个特殊方法,它可将一个类实例变成一个可调用对象
    def __call__(self, *args, **kwargs):
        start_time = time.time()
        self.func()
        print('运行时间:', time.time() - start_time)


@Decoretor
def func():
    time.sleep(0.5)
    print('test--------')


func()

运行结果:

Decoretor---------
test--------
运行时间: 0.5007145404815674

虽然没有创建对象,依然执行了__init__方法,即Decoretor被调用

被装饰的函数有不定长参数
from time import ctime, sleep


def timefun(func):
    def wrapped_func(*args, **kwargs):
        print("%s called at %s"%(func.__name__, ctime()))
        func(*args, **kwargs)
    return wrapped_func


@timefun
def foo(a, b):
    print(a+b)
if __name__ == '__main__':
	foo(3,5)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值