Python中的闭包与装饰器

1.闭包

在Python中,闭包是一个重要的概念,它涉及到一个嵌套函数(内部函数)及其引用的外部函数(或全局)作用域中的变量。简单来说,闭包就是一个可以记住并访问其所在的词法环境的函数,即使该函数在其所在的词法环境之外被执行。

闭包有三个关键点:一是外部函数嵌套内部函数,二是外部函数将内部函数返回,三是内部函数可以访问外部函数的非全局变量。

下面是一个简单的Python闭包示例:

def fun1():
    print("我是fun1")
    datas = []

    def fun2():
        print("我是fun2", datas)

    return fun2


r = fun1()      # 我是fun1
r()     # 我是fun2 []

这是一个简单的闭包,当调用 fun1() 时,它会执行以下操作:

打印 "我是fun1"

创建一个空的列表 datas

定义内部函数 fun2

返回内部函数 fun2 的引用,但并没有执行 fun2

总之,r = fun1()的操作是调用函数fun1并将fun1的返回值(fun2)返回给r,而r()的操作则是调用函数fun2,并打印datas。

这段代码也正好验证了上方提到的闭包的三条关键点。

2.装饰器

Python中的装饰器是一种高级特性,允许程序员在不修改现有函数或类的情况下,为其添加额外的功能。装饰器本质上是一个函数,这个函数接受一个函数(或类)作为参数,并返回一个新的函数(或类),这个新的函数(或类)包装了原始函数(或类)并提供了额外的功能。

以下是装饰器的一些基本特性:

语法糖:装饰器使用@符号作为前缀,使得添加额外功能变得简单明了。

不修改原函数:装饰器可以在不修改原函数代码的情况下,为其添加功能。

可扩展性:可以组合使用多个装饰器,为函数或类添加多个额外的功能。

装饰器既可以对无参函数进行装饰,也可以对含参函数进行装饰。

3.装饰器案例

下方是一个记录两种不同的排序时间的装饰器案例:

import random
import copy
import time

datas = [random.randint(0, 10000) for i in range(10000)]
datas_copy = copy.deepcopy(datas)


# print(datas == datas_copy, datas is datas_copy)

def time_cost(f):
    def calc(sort_type):
        start = time.time()
        f(sort_type)
        print(f"函数{f.__name__}消耗{time.time() - start}")

    return calc


# @time_cost
def my_fun1(sort_type):
    datas.sort(reverse=sort_type)
    print(datas)


# my_fun1(False)

# @time_cost
def my_fun2(sort_type):
    new_datas = sorted(datas_copy, reverse=sort_type)
    print(new_datas)


# my_fun2(False)

# 返回my_fun1 其实就是calc
my_fun1 = time_cost(my_fun1)
# 相当于执行calc
my_fun1(True)

my_fun2 = time_cost(my_fun2)
my_fun2(True)

这个装饰器通过对两种排序方式进行取时间差的方式,来比较哪个方式执行的速度更快、用时更短。

下方是一个简单的权限校验的装饰器:

# 当前登录用户
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(f"用户名密码错误")

    return check


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


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


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


# index()
# center()
# cart()

index()

# center = login_required(center)
center()

# cart = login_required(cart)
cart()

这个装饰器通过对用户访问特定页面时增加权限校验来控制注册用户与游客的访问权限。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值