python装饰器详解

什么是装饰器?
通常的用法,装饰器就是用来装饰函数的

我们在什么情况下会使用到装饰器?
普遍情况下是,我们需要用到一个函数,但是这个函数被其他地方调用,且这个函数的功能无法满足此需求,这样我们就可以通过装饰器来使得函数满足现在的需求,且不影响其他地方。
可以说是拓展函数的功能

一、装饰器入门

# 这是装饰函数
def timer(func):
    def wrapper(*args, **kw):
        t1 = time.time()
        # 这是函数真正执行的地方
        func(*args, **kw)
        t2 = time.time()

        # 计算下时长
        cost_time = t2-t1
        print("花费时间:{}秒".format(cost_time))
    return wrapper


# 入门用法:时间计时器#
@timer
def want_sleep(sleep_time):
    time.sleep(sleep_time)


want_sleep(1)

返回:
在这里插入图片描述

二、带参数的装饰器

# 进阶用法:带参数的函数装饰器#
def say_hello(contry):
    def wrapper(func):
        def deco(*args, **kwargs):
            if contry == "china":
                print("你好!")
            elif contry == "america":
                print('hello.')
            else:
                return

            # 真正执行函数的地方
            func(*args, **kwargs)
        return deco
    return wrapper


@say_hello("china")
def american():
    print("我来自中国。")


@say_hello("america")
def chinese():
    print("I am from America.")


american()
print("------------")
chinese()

返回:
在这里插入图片描述

三、不带参数的类装饰器

class Logger(object):
    def __init__(self, func):
        self.func = func

    def __call__(self, *args, **kwargs):
        print("[INFO]: the function {func}() is running...".format(func=self.func.__name__))
        print("[INFO]: the function {}() is running...".format(self.func.__name__))

        return self.func(*args, **kwargs)


@Logger
def say(something):
    print("say {}!".format(something))


say("hello")

返回:
在这里插入图片描述
以上还展示了format加函数的两种方式,展现效果都一样

tip:
def call(self, *args, **kwargs)的用法
只要定义类型的时候,实现__call__函数,这个类型就成为可调用的。 换句话说,我们可以把这个类型的对象当作函数来使用,相当于 重载了括号运算符。我们可以 实例对象()
总的来说,当一个类型实现了特殊方法__call__,该类的实例就变成了可调用的类型, 对象名() 等价于 对象名.call() ,有时候可以简化对象的调用,让对象变成可调用的对象, 实现__call__即可.

四、使用偏函数与类实现装饰器

import functools
import time

class DelayFunc:
    def __init__(self, duration, func):
        self.duration = duration
        self.func = func

    def __call__(self, *args, **kwargs):
        print(f'Wait for {self.duration} seconds...')
        time.sleep(self.duration)
        return self.func(*args, **kwargs)

    def eager_call(self, *args, **kwargs):
        print('Call without delay')
        return self.func(*args, **kwargs)


def delay(duration):
# 装饰器:推迟某个函数的执行。
# 同时提供 .eager_call 方法立即执行
    # 此处为了避免定义额外函数,
    # 直接使用 functools.partial 帮助构造 DelayFunc 实例
    return functools.partial(DelayFunc, duration)


@delay(duration=0)
def add(a, b):
    print(a+b)
    return a+b


add(3, 5)

返回:
在这里插入图片描述
对于不了解偏函数的,可以搜索了解一下

五、装饰类的装饰器

instances = {}

def singleton(cls):
    def get_instance(*args, **kw):
        cls_name = cls.__name__
        print('===== 1 ====')
        if not cls_name in instances:
            print('===== 2 ====')
            instance = cls(*args, **kw)
            instances[cls_name] = instance
        return instances[cls_name]
    return get_instance


@singleton
class User:
    _instance = None

    def __init__(self, name):
        print('===== 3 ====')
        self.name = name


a1 = User('wangbm1')
a2 = User('wangbm2')

返回:
在这里插入图片描述
a1按顺序执行了1.2.3,但是到a2的时候instances中已经有哦cls_name了,所以不走if not 直接return了

tips:
**kargs:输入数据长度不确定,系统自动将任意长度参数用dict(字典)表示
args:输入数据长度不确定,通过args将任意长度的参数传递给函数,系统自动将任意长度参数用list(tuple定长,特殊的list)表示

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值