简单的装饰器

简单的装饰器

一、解释

给被装饰器添加新的功能。但必须要遵循开放封闭原则(a. 不改变被装饰对象的源代码。b. 不改变被装饰对象的调用方式。)

  1. 开发封闭原则:
  • 开发:对扩展开放。
  • 封闭:对修改封闭。

二、需求:统计index()的运行时间。

  1. 方案一,常规方式。
# 统计index()的运行时间
import time
def index():
    time.sleep(3)  # cpu睡3秒
    print("hello word!")

start = time.time()
index()
end = time.time()
print("index run time:%s"%(end - start))

>> hello word!
>> index run time: 3.001300096511841
  1. 方案二,运用装饰器。
  • 第一步满足闭包,不改变原函数代码。
# 运用装饰器统计index()的运行时间
import time


def index():
    time.sleep(3)  # cpu睡3秒
    print("hello word!")

def outter(func):
    def get_time():
        start = time.time()
        func()
        end = time.time()
        print("index run time: %s" % (end - start))
    return get_time
res = outter(index)
res()

>> hello word!
>> index run time: 3.001300096511841

需要注意的是,此方法源代码没有改变,但是改变了index()的调用方式outter(index)

  • 第二步,不改变调用方式,且给index()增加get_time()函数的功能。
# 运用装饰器统计index()的运行时间
import time


def index():
   time.sleep(3)  # cpu睡3秒
   print("hello word!")

def outter(func):
   def get_time():
       start = time.time()
       func()
       end = time.time()
       print("index run time: %s" % (end - start))
   return get_time
index = outter(index)   # outter(最原始的index函数的内存地址)
print(index)            # 此处的index指向get_time函数的内存地址。
index()                 # 与最原始的调用方式一致,只不过此处的index不是最开始的index了
  • 第三步,提炼成装饰器。
# 运用装饰器统计index()的运行时间
import time


def outter(func):
    def get_time():
        start = time.time()
        func()
        end = time.time()
        print("index run time: %s" % (end - start))

    return get_time


# index = outter(index)   # outter(最原始的index函数的内存地址)
# print(index)            # 此处的index指向get_time函数的内存地址。
# index()                 # 与最原始的调用方式一致,只不过此处的index不是最开始的index了
@outter   # 装饰器outter
def index():
    time.sleep(3)  # cpu睡3秒
    print("hello word!")


index()
  • 第四布,优化,增加不定参数。
# 运用装饰器统计index()的运行时间
import time


def outter(func):
    def get_time(*args, **kwargs):     # args 接收元组,kwargs 接收字典 
        start = time.time()
        func(*args, **kwargs)
        end = time.time()
        print("index run time: %s" % (end - start))

    return get_time


# index = outter(index)   # outter(最原始的index函数的内存地址)
# print(index)            # 此处的index指向get_time函数的内存地址。
# index()                 # 与最原始的调用方式一致,只不过此处的index不是最开始的index了
@outter
def index():
    time.sleep(3)  # cpu睡3秒
    print("hello word!")

@outter
def index2(name):
    time.sleep(2)
    print("%s 是参数,有参函数" % (name))


index2("小明")

无参函数和有参函数都可以直接调用,函数可以接收任意数量的参数。

  • 第五步,不改变原函数返回值。
# 1. 闭:定义在函数内部的函数。
# 2. 包:内部函数引用了外部函数作用域的名字。
# def outter():
#     x = 111
#     def inner():
#         print(x)
#     return inner
# res = outter()
# res()

# 给函数体传值的第一种方式
# def fun(x, y):
#     if x > y:
#         return x
#     return y
#
#
# print(fun(1, 2))


# 给函数体传值的另一种方式--闭包
# def outter(x, y):
#     # x = 1
#     # y = 2
#
#     def max():
#         if x > y:
#             return x
#         return y
#
#     return max()
#
#
# print(outter(1, 4))

# 统计index()的运行时间
# import time
# def index():
#     time.sleep(3)  # cpu睡3秒
#     print("hello word!")
#
# start = time.time()
# index()
# end = time.time()
# print("index run time:%s"%(end - start))


# 运用装饰器统计index()的运行时间
import time


def outter(func):
    def get_time(*args, **kwargs):
        start = time.time()
        res = func(*args, **kwargs)
        end = time.time()
        print("index run time: %s" % (end - start))
        return res

    return get_time


# index = outter(index)   # outter(最原始的index函数的内存地址)
# print(index)            # 此处的index指向get_time函数的内存地址。
# index()                 # 与最原始的调用方式一致,只不过此处的index不是最开始的index了
@outter  # index = outter(index)
def index():
    time.sleep(3)  # cpu睡3秒
    print("hello word!")
    return "index"


@outter    # index2 = outter(index2)
def index2(name):
    time.sleep(2)
    print("%s 是参数,有参函数" % (name))
    return "index2"


print(index2("小明"))

>> 小明 是参数,有参函数
>> index run time: 2.0031635761260986
>> index2

注:语法糖@outter会将它紧挨着的函数名当作第一个参数直接传入,直接调用。不改变调用,返回,传值。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zhxl1631_163_com

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值