python 类的装饰器

# 将函数当作参数传入装饰器

# 入门用法:日志打印器
def logger(func):
    def wrapper(*args,**kw):
        # *args的用法:当传入的参数个数未知,且不需要知道参数名称时
        # 会将调用时的key=value参数全部打包到kw这个dict对象内
        print('准备开始执行:{}函数了'.format(func.__name__))

        # 真正执行的是这行
        func(*args,**kw)

        print('计算完毕!')

    return wrapper

@logger
def add(x,y):
    print('{}+{}={}'.format(x,y,x+y))

add(200,20)

# 入门用法:时间计时器
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

import time

@timer
def want_sleep(sleep_time):
    time.sleep(sleep_time)

want_sleep(10)

# 进阶:带参数的装饰器 根据国籍打招呼
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 chinese():
    print('来自中国')

@say_hello("america")
def america():
    print('from america')

chinese()
america()

# 不带参数的类装饰器
# __init__:接收被装饰函数
# __call__:实现装饰逻辑
class logger(object):
    def __init__(self,func):
        self.func=func

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

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

@logger
def say(sth):
    print('say {}!'.format(sth))

say('hello')

# 高阶:带参数的类装饰器
# __init__:不再接收被装饰函数,而是接收传入参数
# __call__:接收被装饰函数,实现装饰逻辑
class logger(object):
    def __init__(self,level='INFO'):
        self.level=level

    def __call__(self,func):
        def wrapper(*args,**kwargs):
            print('[{}]:the function {}() is running...'.format(self.level,func.__name__))
            func(*args,**kwargs)
        return wrapper # 返回函数

@logger(level='WARNING')
def say(sth):
    print('say {}!'.format(sth))

say('hello')

# 使用偏函数与类实现装饰器
# 偏函数:functools.partial的作用就是,把一个函数的某些参数给固定住(也就是设置默认值),返回一个新的函数,调用这个新函数会更简单。

import time
import functools

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.partitial帮助构造DelayFunc 实例
    return functools.partial(DelayFunc,duration)

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

add(3,5)


# wraps装饰器有什么用?偏函数对象
# 方法一

from functools import wraps

def wrapper(func):
    @wraps(func)
    def inner_function():
        pass
    return inner_function

@wrapper
def wrapped():
    pass

print(wrapped.__name__)

# 方法二
from functools import update_wrapper

WRAPPER_ASSIGNMENTS = ('__module__', '__name__', '__qualname__', '__doc__',
                       '__annotations__')

def wrapper(func):
    def inner_function():
        pass

    update_wrapper(inner_function, func, assigned=WRAPPER_ASSIGNMENTS)
    return inner_function

@wrapper
def wrapped():
    pass

print(wrapped.__name__)

# 内置装饰器:property
# 存在于类中,可以将一个函数定义成一个属性,属性的值就是函数return的内容
# 同时会将这个函数变成另外一个装饰器,比如使用的@age.setter和@age.deleter
class Student(object):
    def __init__(self, name):
        self.name = name
        self.name = None

    @property
    def age(self):
        return self._age

    @age.setter
    def age(self, value):
        if not isinstance(value, int):
            raise ValueError('输入不合法:年龄必须为数值!')
        if not 0 < value < 100:
            raise ValueError('输入不合法:年龄范围必须0-100')
        self._age = value

    @age.deleter
    def age(self):
        del self._age


XiaoMing = Student("小明")

# 设置属性
XiaoMing.age = 25

# 查询属性
print(XiaoMing.age)

# 删除属性
del XiaoMing.age

# 原文章链接:https://www.jb51.net/article/168276.htm
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值