《装饰器的奇妙物语:为代码披上华丽外衣》

1.1闭包(Closure)

闭包是指在一个函数内部定义另一个函数,并且内部函数可以访问外部函数的变量,即使外部函数已经执行完毕。

1.1闭包的概念:
闭包的形成需要满足以下条件:

  1. 存在一个嵌套函数(即在一个函数内部定义的函数)。
  2. 嵌套函数引用了外部函数的变量。
  3. 外部函数返回了嵌套函数。

按照步骤走就可以形成闭包

以下举一个例子:

#外层方法
def outer_function(x):
    # 内层方法
    def inner_function(y):
        # 内层函数调用外层函数的局部变量
        return x + y
    
    #外层方法返回内层函数
    return inner_function
closure = outer_function(5)
print(closure(3))  # 输出 8

在介绍一个闭包的进阶方法:

我们将一个列表进行排序并且计算排序消耗的时间:

data = [random.randint(1, 10000) for i in range(1000)]


def my_time(f):
    def cacl(reverse_type):
        start = time.time()
        f(reverse_type)
        print(time.time() - start)

    return cacl

@my_time
def my_fun1(reverse_type):
    data.sort(reverse=reverse_type)
    print(data)

@my_time
def my_fun2(reverse_type):
    datas = sorted(data.copy(), reverse=reverse_type)
    print(datas)


# my_fun1 = my_time(my_fun1)
my_fun1(True)

输出结果:

我们通过使用@my_time来省略了my_fun1= my_time(my_fun1)的代码,但是@my_time的底层逻辑还是my_fun1= my_time(my_fun1。

2.装饰器

2.1装饰器的概念:

装饰器(decorators)是 Python 中的一种高级功能,它允许你动态地修改函数或类的行为。

装饰器是一种函数,它接受一个函数作为参数,并返回一个新的函数或修改原来的函数。

装饰器的语法使用 @decorator_name 来应用在函数或方法上。

Python 还提供了一些内置的装饰器,比如 @staticmethod 和 @classmethod,用于定义静态方法和类方法。

2.2装饰器的应用场景:

  • 日志记录: 装饰器可用于记录函数的调用信息、参数和返回值。
  • 性能分析: 可以使用装饰器来测量函数的执行时间。
  • 权限控制: 装饰器可用于限制对某些函数的访问权限。
  • 缓存: 装饰器可用于实现函数结果的缓存,以提高性能。

2.3装饰器的使用

Python 装饰允许在不修改原有函数代码的基础上,动态地增加或修改函数的功能,装饰器本质上是一个接收函数作为输入并返回一个新的包装过后的函数的对象。

这里我们来举一个排序的例子,我们需要在不改变原函数(排序函数)的情况下计算排序消耗了多少时间,

data = [random.randint(1, 10000) for i in range(1000)]


def my_time(f):
    def cacl(reverse_type):
        # 原函数执行前的增强功能
        start = time.time()
        # 原函数  原函数不需要被改变
        f(reverse_type)
        # 原函数执行后的增强功能
        print(time.time() - start)

    return cacl

@my_time
def my_fun1(reverse_type):
    data.sort(reverse=reverse_type)
    print(data)
    
    
    # 参数是来确认排序是正序还是逆序
my_fun1(True)

这里再举一个例子来帮助加深理解。现在我们做一个模拟登录的系统。我们先进入首页,然后进入个人中心需要验证用户,进入购物车也需要验证,这里我们设置一个user全局变量来模拟用户登录。在不改变个人中心和购物车原有功能的情况下来增加一个验证用户的功能。

user = None


def login_required(f):
    def check():
        global user
        if user:
            # 原函数
            f()
       # 增强的功能
        else:
            while True:
                username = input("请输入用户名")
                password = input("请输入密码")
                if username == "admin" and password == "123456":
                    user = "admin"
                    f()
                    break
                else:
                    print("用户名或密码输入错误")
    return check


def index():
    print(f"我是首页")


@login_required
def center():
    print(f"我是个人中心")


@login_required
def cart():
    print(f"我是购物车")


index()

center()

cart()

运行结果如下:

第二个例子:使用统计使用冒泡排序与选择排序时间开销

# 装饰器统计使用冒泡排序与选择排序时间开销
import random
import time

datas = [random.randint(0, 10000) for i in range(10000)]
datas2 = datas.copy()
datas3 = datas.copy()
datas4 = datas.copy()

def time_difference(f):
    def calc():
        start = time.time()
        f()
        print(f"时间差{time.time()-start}")
    return calc




def my_fun1():
    datas.sort()
    print(datas)


def my_fun2():
    new_datas = sorted(datas2)
    print(new_datas)

@time_difference
def my_fun3():
    for i in range(len(datas3) - 1):
        for j in range(len(datas3) - 1 - i):
            if datas3[j] > datas3[j + 1]:
                temp = datas3[j]
                datas3[j] = datas3[j + 1]
                datas3[j + 1] = temp
    print(datas3)


# my_fun3 = time_difference(my_fun3)
my_fun3()

@time_difference
def my_fun4():
    for i in range(len(datas4) - 1):
        min_index = i
        for j in range(i + 1, len(datas4)):
            if datas4[min_index] > datas4[j]:
                min_index = j
        if min_index != i:
            temp = datas4[i]
            datas4[i] = datas4[min_index]
            datas4[min_index] = temp
    print(datas4)


# my_fun4 = time_difference(my_fun4)
my_fun4()

运行结果:

3 总结

装饰器不仅可以用函数来实现,也可以用类来实现。类装饰器(之后介绍)的实现方式略有不同,但基本思想是类似的,都是通过定义一个类来对函数进行装饰和功能增强。

如果你想在其他编程语言中使用类似装饰器的功能,可能会有不同的实现方式,具体取决于该语言的特性和设计模式。例如在某些情况下,可能会使用代理、包装器或其他类似的概念来达到类似的效果。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值