【python】装饰器

装饰器

1.装饰器入门
  • 装饰器的作用:在不改变源代码和源代码调用方式的基础上,增加新的功能;

  • 装饰器使用:

comment = decorator(comment)
@decorator
  • 写法:
def decorator(fn):	# fn=0x22

def inner():		# 0x33
	print("请先登录...")
	fn()
	return inner	# return 0x33

@decorator
def comment():		# 0x22
	print("发表评论")


# comment = decorator(comment)
# comment是闭包对象=0x33
comment()		    # 0x33()
  • 注意:语法糖写法,装饰器会在模块加载的那刻进行装饰。
2.装饰器的使用
  • 装饰器实现已有函数执行时间的统计

# 使用装饰器统计函数的执行时间
import time


def decorator(fn):

 def inner():
     start = time.time()
     fn()
     end = time.time()

     print("改函数执行共花费时间: ", (end-start))

 return inner


@decorator  # 等价于 foo=decorator(foo)
def foo():
 for i in range(100000):
     print(i)


if __name__ == '__main__':
 foo()

3.通用装饰器
  • 普通参数
def decorator(fn):

 def inner(num1, num2):
     print("扩展功能")
     fn(num1, num2)

 return inner

@decorator
def foo(a, b):
 result = a + b
 print("result: ", result)
  • 可变参数

def decorator(fn):

 def inner(*args, **kwargs):
     print("扩展功能...")
     fn(*args, **kwargs) # 拆包再传递参数
     # fn(args, kwargs)

 return inner


@decorator
def foo(*args, **kwargs):
 print(args, kwargs)
 result = 0

 for i in args:
     result += i

 for i in kwargs.values():
     result += i

 print("result: ", result)

  • 有返回值
def decorator(fn):

 def inner(num1, num2):

     print("扩展功能...")
     result = fn(num1, num2)
     return result

 return inner


@decorator  # foo=decorator(foo)
def foo(a, b):
 result = a + b
 return result

  • 结论:内层函数的原型必须和被装饰函数一样。
  • 通用装饰器
  • 作用:可以装饰不定长参数的函数和有返回值的函数。
  • 格式
def decorator(fn):

  	def inner(*args, **kwargs):
      	print("扩展功能...")
      	result = fn(*args, **kwargs)
        print("扩展功能")
        return result
      
    return inner
  • 使用:
# 内层函数的结构应该和待装饰函数的结构一样
# 通用装饰器

def decorator(fn):
    def inner(*args, **kwargs):
        print("扩展功能...")
        result = fn(*args, **kwargs)
        print("扩展功能2...")
        return result

    return inner


@decorator
def foo(a, b):
    result = a + b
    print("result: ", result)


@decorator
def foo2(a, b):
    result = a + b
    return result


@decorator
def foo3(*args, **kwargs):
    print(args, kwargs)
    result = 0

    for i in args:
        result += i

    for i in kwargs.values():
        result += i

    print("result: ", result)


@decorator
def foo4():
    print("发表评论....")

if __name__ == '__main__':
    # foo(10, 20)

    # ret = foo2(10, 20)
    # print("ret: ", ret)

    # foo3(1, 2, 3, a=10, b=20)

    foo4()
4.多重装饰器
  • 多重装饰器:一个函数被多个装饰器装饰

  • 装饰原则:

    多个装饰器可以对函数进行多个功能的装饰,装饰顺序是由内到外的进行装饰,调用顺序正好相反。
    
  • 代码:

def make_div(fn):   # 0x11  fn=0x44
    print("make_div被调用")
    def inner():    # 0x55
        print("make_div中的inner被调用")
        return "<div>" + fn() + "</div>"

    return inner


def make_p(fn):     # 0x22  fn=0x33
    print("make_p被调用")
    def inner():    # 0x44
        print("make_p中的inner被调用")
        return "<p>" + fn() + "</p>"

    return inner


@make_div   # content = make_div(content) --> content = 0x55
@make_p     # content = make_p(content) --> content = 0x44
def content():      # 0x33
    print("源函数被调用")
    return "人生苦短"


if __name__ == '__main__':
    result = content()      # 0x55()
    print(result)
5.带有参数的装饰器
  • 语法格式:
def logging(flag):
	
	def decorator(fn):
     def inner(*args, **kwargs):
         print("扩展功能...")
						if flag == "+":
           	print("努力做加法....")
         elif flag == "-":
           	print("努力做减法....")
             
         result = fn(*args, **kwargs)
         return result

     return inner

return decorator

@logging("+")
def add(a, b):
 result = a + b
 print("result: ", result)


@logging("-")
def sub(a, b):
 result = a - b
 print("result: ", result)


if __name__ == '__main__':
 add(10, 20)

 sub(100, 50)

6.类装饰器
  • 作用:使用类来实现闭包

  • 类的书写:
    def init(self, fn):
    def call(self, *args, **kwargs):

# 装饰器函数
# def func_out(fn):
#
#     def func_in():
#         print("请先登录")
#         fn()
#
#     return func_in

# @func_out
# def comment():
#     print("发表评论")

# 类装饰器
class Check(object):

    def __init__(self, fn): # fn=0x11
        self.__fn = fn      # self.__fn = 0x11
                            # self.__fn = 0x22


    def __call__(self, *args, **kwargs):
        print("请先登录")
        result = self.__fn(*args, **kwargs)
        return result


@Check      # comment = Check(comment) --> comment 是 Check类的对象
def comment():  # 0x11
    print("发表评论")


@Check      # foo = Check(foo) --> foo 是 Check类的对象
def foo(a, b):  # 0x22
    result = a + b
    return result

if __name__ == '__main__':
    comment()   # 对象() --> __call__(对象)


    ret = foo(10, 20)
    print(ret)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值