Python 闭包和装饰器的讲解

博客主要介绍了Python中的闭包和装饰器,闭包和装饰器是Python编程里重要的概念,在代码复用和功能扩展等方面有重要作用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1, 闭包。

一、定义说明:
在Python中,函数内部可以定义函数(函数名其实就是指向一段内存空间的地址,即函数名就是函数的入口地址)。
闭包函数必须满足两个条件: 1.函数内部定义的函数 2.包含对外部作用域而非全局作用域的引用。
例1:
def a(a, b):
    def c(x):
        return a*x + b
    print(c.__closure__)
    return c
# 调用
print(a(3, 4)(8))
二、优缺点说明
1、实现了代码的可复用性
2、闭包似优化了变量,原来需要类对象完成的工作,闭包也可以完成
3、由于闭包引用了外部函数的局部变量,则外部函数的局部变量没有及时释放,消耗内存(闭包调用时候,如果内部函数没有调用,其内存资源得不到释放。)

2,装饰器

一、定义
装饰器:外部函数传入被装饰函数名,内部函数返回装饰函数名。
特点:1.不修改被装饰函数的调用方式 2.不修改被装饰函数的源代码
python装饰器就是用于拓展原来函数功能的一种函数,这个函数的特殊之处在于它的返回值也是一个函数,使用python装饰器的好处就是在不用修改原函数的代码前提下给函数增加新的功能。其实通俗一点讲,其实装上器就是闭包的功能的扩展。
举例:
def w1(func):
    def inner():
        # 验证1
        # 验证2
        # 验证3
        func()
    return inner
@w1
def f1():
    print('f1')
简单的运行原理:
在调用f1函数时,其实通过@w1(语法糖)将f1(函数入口地址传递给w1函数的参数func,并将w1的返回值传递给原来的f1所在的位置。),那么执行函数f1时,其实就是执行了w1(f1)(),这样就实现在没有改变原来代码的情况下,扩展了原来的功能,而且没有改变原来的函数名。
二、多个装饰器。
def makeBold(fn):
    def wrapped():
        return "<b>" + fn() + "</b>"
    return wrapped
def makeItalic(fn):
    def wrapped():
        return "<i>" + fn() + "</i>"
    return wrapped
@makeBold
@makeItalic
def test3():
    return "hello world-3"
print(test3())
运行结果:<b><i>hello world-3</i></b>
原理和上面就讲解的一样,不再赘余。
三、带关于带参数的装饰器。
1、第一种(一般参数)
def timefun(func):
    def wrappedfunc(a, b):
        print(a, b)
        func(a, b)
    return wrappedfunc
@timefun
def foo(a, b):
    print(a+b)
foo(8, 9)
输出结果:
8 9
17
2、第二种(不定长参数)。
def timefun(func):
    def wrappedfunc(*args, **kwargs):
        func(*args, **kwargs)
    return wrappedfunc
@timefun
def foo(a, b, c):
    print(a+b+c)
foo(3,5,7)
运行结果:
15
3、有返回值
def timefun(func):
    def wrappedfunc():
        print(5445)
        return func()
    return wrappedfunc
@timefun
def getInfo():
    return '----hahah---'
print(getInfo())
结果:
5445
----hahah---
4、在原有的基础上在添加参数。
def timefun_arg(pre="hello"):
    def timefun(func):
        def wrappedfunc():
            print(pre)
            return func()
        return wrappedfunc
    return timefun
@timefun_arg("dcg")
def foo():
    print("I am foo")
foo()
5、类装饰器
(主要重写__call__方法。)
对__call__方法进行讲解:
class Foo(object):
    def __init__(self, func):
        self._func = func
    def __call__(self):
        print('class decorator runing')
        self._func()
        print('class decorator ending')
@Foo  # bar = Foo(bar)
def bar():
    print('bar')
bar()  # Foo(bar)()
# 结果
# class decorator runing
# bar
# class decorator ending

例子:

# 装饰函数的装饰器
def count_time_function(func):
    """
    计算函数执行的时间
 
    :param func:
    :return:
    """
    def inner_method(*args, **kwargs):
        start_time = time.time()
        result = func(*args, **kwargs)
        end_time = time.time()
        sub_time = end_time - start_time
        Logger().to_log(level='info', message='当前' + str(func) + '函数的执行时间为:' + str(sub_time) + '秒')
        return result
    return inner_method


#  装饰类的装饰器
def count_time_class(newCls):
    """
    计算类的执行时间
    :param newCls:
    :return:
    """
    class NewClass(newCls):
        def __init__(self, *args, **kwargs):
            # self.new_class = newCls(*args, **kwargs)
            self.start_time = time.time()
            super().__init__(*args, **kwargs)

        def __del__(self):
            self.end_time = time.time()
            self.sub_time = self.end_time - self.start_time
            Logger().to_log(level='info', message='当前' + str(newCls) + '类的执行时间为:' + str(self.sub_time) + '秒')
            del self

    return NewClass


# 带参数的装饰器,用来记录一家公司
def count_time_one_request(common_data):
    def time_fun(func):
        def run_fun(*args, **kwargs):
            start_time = time.time()
            result = func(*args, **kwargs)
            end_time = time.time()
            sub_time = end_time - start_time
            print('common_data1111', common_data)
            task_type_name = get_task_name(common_data)
            Logger().to_log(level='info', message='当前'+str(common_data['national_name']) + '的' + task_type_name +
                                                  '任务的执行时间为:' + str(sub_time) + '秒')
            return result
        return run_fun
    return time_fun
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值