Python3学习Python小推车python学习

Python学习打call第二十一天:装饰器

2019-02-19  本文已影响28人  暖A暖

1.什么是装饰器

2.装饰器特点

3.无参装饰器

# 例1:这就是装饰器的原型,目的是对add函数增强,在add执行的前后可以做一些操作。
def add(x, y):
    return x + y
def decorator(fn):
    def wrapper(*args, **kwargs):
        print('start')
        result = fn(*args, **kwargs)
        print('end')
        return result
    return wrapper
wrapper = decorator(add)
result = wrapper(x=1, y=2)
print(result)

# 例2:可以将例1的调用过程进行改造
def add(x, y):
    return x + y
def decorator(fn):
    def wrapper(*args, **kwargs):
        print('start')
        result = fn(*args, **kwargs)
        print('end')
        return result
    return wrapper
result = decorator(add)(x=1, y=2)
print(result)


# 例3:decorator 就是装饰器函数,add就是被装饰的函数
def decorator(fn):
    def wrapper(*args, **kwargs):
        print('start')
        result = fn(*args, **kwargs)
        print('end')
        return result
    return wrapper

#这是Python的装饰器语法糖,@decorator相当于对add函数进行了一次调用,返回的是wrapper
@decorator
def add(x, y):
    return x + y
result = add(x=1, y=2)
print(result)


# 例4:解决被装饰器装饰的函数属性不一致的问题
import functools
def decorator(fn):
    @functools.wraps(fn)
    def wrapper(*args, **kwargs):
        print('start')
        result = fn(*args, **kwargs)
        print('end')
        return result
    return wrapper

@decorator
def add(x, y):
    return x + y
result = add(x=1, y=2)
print(result)
print(add.__name__)  # add

4.带参装饰器

import functools
import datetime
import time

def decorator(t): # 这里只是一个简单的函数
    def timer(fn): # 这里才是装饰器
        @functools.wraps(fn)
        def wrapper(*args, **kwargs):
            '''
            this is a wrap function
            '''
            print("args={} kwargs={}".format(args,kwargs))
            start = datetime.datetime.now()
            ret = fn(*args, **kwargs)
            end = datetime.datetime.now()
            duration = (end - start).total_seconds()
            if duration > t:
                print('Time out')
            return ret
        return wrapper
    return timer

@decorator(2)
def add(x,y):
    '''
    :param x:
    :param y:
    :return: 返回x + y的结果
    '''
    time.sleep(3)  # 延迟3秒
    return x + y
add(1,2)
print(add.__name__, add.__doc__, sep='\n')

5.functools模块

@functools.wraps(fn)

6.装饰器在不同场景下的使用

(1)带参装饰器:不返回包裹函数

# 这里装饰器返回的并不是包裹的wrapper函数,因为这里没有wrapper函数,而是被装饰的函数本身
# 这里装饰器的意义在于:调用被装饰函数之前可以做一些事情
import datetime
import time
def decorator(t):
    def timer(fn):
        start = datetime.datetime.now()
        duration = (datetime.datetime.now() - start).total_seconds()
        print(duration)  # 0.0
        print(t)  # 2
        return fn
    return timer
@decorator(2)
def add(x,y):
    time.sleep(2)
    return x+y
print(add(1,2))
print(add.__name__)

(2)不带参装饰器:不返回包裹函数,返回原始函数本身

# 不带参数的装饰器,直接返回被装饰函数本身,在原始函数之前做一些事情
import time
def decorator(fn):
    print('调用函数之前我可以做些事情')
    return fn
@decorator
def add(x,y):
    time.sleep(2)
    print(x+y)  # 3
add(1,2)

(3)函数装饰器装饰类:返回原始类本身(带参数)

def dec(cls):
    cls.num = 100
    return cls
@dec
class Person(): # Person = cls
    def __init__(self):
        pass
print(Person.num) # 100

(4)函数装饰器装饰类:返回原始类本身(带参数)

def dec(num):
    def wrapper(cls): # 这里的cls就是Person类
        cls.num = num
        return cls
    return wrapper
# 这种带参数的装饰器就理解为函数调用即可
@dec(100)
class Person():
    def __init__(self):
        pass
print(Person.num) # 100

7.类装饰器

import datetime
import time
from functools import wraps
# 这是上下文管理的类
class Decorator:
    '''this is dec class '''
    def __init__(self, fn):
        if fn is not None:
            self.fn = fn
            wraps(fn)(self)  # 这里是将fn的属性赋值给self实例,因为self实例会返回
    def __call__(self, *args, **kwargs):
        self.start = datetime.datetime.now()
        ret = self.fn(*args, **kwargs)
        self.interval = (datetime.datetime.now() - self.start).total_seconds()
        return 'interval is {}, result is {}'.format(self.interval, ret)
# 被装饰的函数
@Decorator    # add = Decorator(add)
def add(x,y):
    ''' this is a function '''
    time.sleep(2) # 延迟2秒
    return x + y
print(add(3,4))  # add调用的是Decorator的实例self,不是以前的函数add了
print(add.__doc__)

参考:侠课岛(9xkd.com)Python同学计划

上一篇 下一篇

猜你喜欢

热点阅读