Python中闭包和装饰器的学习攻略

 更新时间:2026年05月19日 10:09:08   作者:颂love  
Python中的闭包和装饰器是两种非常重要的编程概念,它们都是基于函数的特性,特别是涉及到作用域和函数的嵌套,这篇文章主要介绍了Python中闭包和装饰器的相关资料,需要的朋友可以参考下

一、闭包

(1)作用域

学习闭包前先要回顾一下作用域的知识:作用域一般分为全局作用域和局部作用域,对应使用的就是全局变量和局部变量;

值得注意的是在局部作用域中可以访问全局变量,而全局作用域中是不能访问局部变量的

原因:Python的底层存在一个内存回收空间,用于加快计算机的运行;变量同样需要占用内存,当局部作用域所代表的函数在运行过后,其内部的变量和程序会被Python当作已经使用过的内存进行回收

既然是范围方面的程序就会有解决的方法,当程序中需要在全局作用域实现对局部变量的访问时,就要用到闭包了

(2)闭包的含义

闭包:函数嵌套的前提下,内部的函数使用了外部函数的变量,外部函数又返回了内部函数,这时这个内部函数就是闭包

(3)闭包的构成

如何区分一个程序是否存在闭包,闭包一般有三步构成的条件

1、存在函数的嵌套

2、有内部函数的对于外部函数的引用

3、有外部函数对内部函数进行返回(即return)

这里需要注意的是,闭包引用了外部函数的变量,所以外部函数的变量运行完外部函数之后其内存并没有得到释放,会消耗内存

经典闭包的构成例子:

def outer():
     num = 20
     def inner():
         print(num)
     return inner

f = outer()
f()

1、存在嵌套函数:outer是外部函数,inner是内部函数

2、内部函数inner引用了外部函数outer中的自由变量num

3、外部函数outer返回了内部函数inner的引用

4、当outer()执行完毕后,返回的inner函数依然可以访问并保留对变量num的绑定,形成闭包

(4)闭包实现对外部变量的修改

这里要引用一个新的关键词nonlocal;它是用于声明函数内部修改函数外部的变量,这个变量不是全局变量

它和global关键字不同就在于global在函数内部声明变量,但这个变量是全局变量

二者在实际的使用是相似的,只是使用的场景和作用不同

闭包实现修改的案例:

def outer():
     res = 20

     def inner(num):
         nonlocal res
         res += num
         print(res)
     return inner

f = outer()
f(1)
f(2)

res作为外部函数的局部变量,num作为内部函数的变量;res+=num就能直接修改res变量,再打印res引用外部函数变量,outer()再返回内部函数inner形成闭包,最后全局使用外部函数,可以看到这时的f(1)和f(2)中res发生了变化,而且是递进改变的

二、装饰器

(1)什么是装饰器

装饰器:在不改变现有函数代码函数调用的前提下,实现给函数增加额外的功能

装饰器本质上也是一个闭包函数

(2)装饰器的定义

def register(fn):
    def inner():
        print('开始注册')
        fn()
    return inner

@register
def login():
    print('登录成功')

login()

register就是一个装饰器函数,接收函数fn为参数;

@register语法就是将装饰器应用于login函数中

调用login时其实是调用了装饰器register中的inner函数,所以先打印开始注册,然后打印登录成功

效果如下:

(3)装饰器的简单使用

import time
def get_time(fn):
    def inner():
        start = time.time()
        fn()
        end = time.time()
        print(f"执行时间为:{end - start}s")
    return inner

@get_time
def demo():
    for i in range(1000000):
        print(i)

demo()

这个装饰器功能用于可以计算下面demo()函数运行完的执行时间,感兴趣可以深入了解一下

(4)装饰器的形式(了解即可)

带参数的装饰器

def log(fn):
    def inner(*args, **kwargs):
        fn(*args, **kwargs)
    return  inner

@log
def demo_1(*args, **kwargs):
    res = 0
    for i in args:
        res += i

    for i in kwargs.values():
        res += i
    print(res)

demo_1(10, 20, a=30, b=40)

关于不定长参数,在之前的Python学习中已经了解了,这里不多阐述

带返回的装饰器

def log(fn):
    def inner(*args, **kwargs):
        return fn(*args, **kwargs)
    return inner

@log
def demo_1(a, b):
    res = a - b
    return res

print(demo_1(20,10))

通用装饰器

def log(fn):
    def inner(*args, **kwargs):
        return fn(*args, **kwargs)
    return inner

@log
def demo_1(a, b):
    res = a + b
    return res

print(demo_1(20,10))

@log
def demo_2(a, b, c):
    res = a + b + c
    return res
print(demo_2(20,10,5))

一般装饰器形式以这个为准

可以看到装饰器的形式一般都大差不差,按照闭包的形式遵循一定的规则,然后调用函数即可

(5)装饰器的扩展(了解)

使用装饰器传递参数

基本语法:

def 装饰器名(形参):
    #代码
@装饰器名('参数')
def 被装饰函数():
    #代码

代码:

def log(flag):
    def f1(fn):
        def inner(*args, **kwargs):
            if flag == '+':
                print("正进行加法运算")
            elif flag == '-':
                print("正进行减法运算")
            return fn(*args, **kwargs)
        return inner
    return f1

@log('+')
def demo_1(a, b):
    res = a + b
    return res

@log('-')
def demo_2(a, b):
    res = a - b
    return res

print(demo_1(20,10))
print(demo_2(100,10))

效果如下:

类装饰器

基本语法:

class 类装饰器():
    #代码

@类装饰器名称
def 函数():
    #代码

代码:

class Check():
    def __init__(self, fn):
        self.__fn = fn

    def __call__(self, *args, **kwargs):
        print("开始检查")
        self.__fn(*args, **kwargs)

@Check
def comment():
    print("正在检查")

comment()

效果如下:

其实就是在装饰器的基础上用到了类的方法

总结

到此这篇关于Python中闭包和装饰器学习攻略的文章就介绍到这了,更多相关Python闭包和装饰器内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 20个Python中正则表达式的应用与技巧小结

    20个Python中正则表达式的应用与技巧小结

    正则表达式是一种用来匹配字符串的模式,它可以在文本中搜索和匹配特定的字符串模式,本文我们将探讨 Python 中 re 模块的应用和一些技巧,希望可以帮助您更好地理解和利用正则表达式
    2024-04-04
  • python实现输出一个序列的所有子序列示例

    python实现输出一个序列的所有子序列示例

    今天小编就为大家分享一篇python实现输出一个序列的所有子序列示例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2019-11-11
  • 排序算法之插入排序法解析

    排序算法之插入排序法解析

    这篇文章主要介绍了排序算法之插入排序法解析,插入排序法是一种简单但有效的排序算法,其基本思想是将一个待排序的元素逐个插入到已经排好序的元素序列中,直至所有元素都被插入完成,从而得到一个有序序列,需要的朋友可以参考下
    2023-07-07
  • Python使用itcaht库实现微信自动收发消息功能

    Python使用itcaht库实现微信自动收发消息功能

    这篇文章主要介绍了Python使用itcaht库实现微信自动收发消息功能,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-07-07
  • 使用Python实现异步文件读写功能

    使用Python实现异步文件读写功能

    在处理大规模数据或多个文件时,同步读写操作会导致程序阻塞,影响整体性能,通过异步文件读写,可以显著提高程序的响应速度和并发处理能力,本文将详细介绍如何使用Python实现异步文件读写,需要的朋友可以参考下
    2025-09-09
  • 解决nohup重定向python输出到文件不成功的问题

    解决nohup重定向python输出到文件不成功的问题

    今天小编就为大家分享一篇解决nohup重定向python输出到文件不成功的问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-05-05
  • selenium自动化测试框架方式

    selenium自动化测试框架方式

    这篇文章主要介绍了selenium自动化测试框架方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2020-02-02
  • jupyter安装小结

    jupyter安装小结

    jupyter (之前的 ipython notebook )于我的最大意义在于,让学习进程和探索进程变得可累积,正如它的原先名字中的 notebook 所暗示的那样,作为学习的记录者,方便你随时捡起学习的进度,增量式地前进
    2016-03-03
  • Python基于更相减损术实现求解最大公约数的方法

    Python基于更相减损术实现求解最大公约数的方法

    这篇文章主要介绍了Python基于更相减损术实现求解最大公约数的方法,简单说明了更相减损术的概念、原理并结合Python实例形式分析了基于更相减损术实现求解最大公约数的相关操作技巧与注意事项,需要的朋友可以参考下
    2018-04-04
  • 亲手教你用Python打造一款摸鱼倒计时界面

    亲手教你用Python打造一款摸鱼倒计时界面

    前段时间在微博看到一段摸鱼人的倒计时模板,感觉很有意思,于是我用了一个小时的时间写一个页面出来,下面小编把实现过程分享给大家,对Python摸鱼倒计时界面感兴趣的朋友一起看看吧
    2021-12-12

最新评论