【Python高阶技巧】闭包、装饰器

一、闭包

  • 1、闭包的用途和用法
  • 2、nonlocal关键字的作用
  • 闭包注意事项 优缺点

二、装饰器

  • 装饰器的作用和用法

一、闭包

在编程中,闭包(Closure)是指一种函数对象,它可以访问其自身范围(词法作用域)之外的变量。换句话说,闭包允许函数访问其创建时所在的词法作用域中的变量,即使在函数执行完毕后,这些变量仍然可以被访问。

闭包通常发生在嵌套函数中。一个函数定义在另一个函数的内部,并且内部函数引用了外部函数的变量,这样的结构就形成了闭包。闭包具有以下特点:

  1. 词法作用域(Lexical Scope): 闭包允许内部函数访问外部函数的词法作用域中的变量,即使外部函数已经执行完毕。

  2. 持久性: 闭包中的变量在外部函数执行完后仍然保持活动状态,因为内部函数引用了这些变量。

下面是一个简单的例子,演示了 JavaScript 中的闭包:

function outerFunction() {let outerVariable = "I am from the outer function";// 内部函数形成闭包,可以访问外部函数的变量function innerFunction() {console.log(outerVariable);}return innerFunction;
}// 调用外部函数,得到内部函数
let closureFunction = outerFunction();// 执行内部函数,它可以访问外部函数的变量
closureFunction(); // 输出: I am from the outer function

在这个例子中,innerFunction 是一个闭包,它引用了外部函数 outerFunction 中的 outerVariable。即使 outerFunction 执行完毕,我们仍然可以通过调用 closureFunction 来访问 outerVariable

闭包在许多编程语言中都存在,并且在函数式编程和一些设计模式中经常被使用。在使用闭包时,需要注意内存管理,确保不会造成不必要的内存泄漏。

1、闭包的用途和用法

在这里插入图片描述
在这里插入图片描述

简单的示例

在这里插入图片描述

2、2、nonlocal关键字的作用

在这里插入图片描述
在这里插入图片描述

代码

"""
演示Python的闭包特性
"""# 简单闭包
# def outer(logo):
#
#     def inner(msg):
#         print(f"<{logo}>{msg}<{logo}>")
#
#     return inner
#
#
# fn1 = outer("黑马程序员")
# fn1("大家好")
# fn1("大家好")
#
# fn2 = outer("传智教育")
# fn2("大家好")# 使用nonlocal关键字修改外部函数的值
# def outer(num1):
#
#     def inner(num2):
#         nonlocal num1
#         num1 += num2
#         print(num1)
#
#     return inner
#
# fn = outer(10)
# fn(10)
# fn(10)
# fn(10)
# fn(10)# 使用闭包实现ATM小案例
def account_create(initial_amount=0):def atm(num, deposit=True):nonlocal initial_amountif deposit:initial_amount += numprint(f"存款:+{num}, 账户余额:{initial_amount}")else:initial_amount -= numprint(f"取款:-{num}, 账户余额:{initial_amount}")return atmatm = account_create()atm(100)
atm(200)
atm(100, deposit=False)

闭包注意事项 优缺点

优点,使用闭包可以让我们得到:

  • 无需定义全局变量即可实现通过函数,持续的访问、修改某个值
  • 闭包使用的变量的所用于在函数内,难以被错误的调用修改

缺点:

  • 由于内部函数持续引用外部函数的值,所以会导致这一部分内存空间不被释放,一直占用内存

总结

  1. 什么是闭包
    定义双层嵌套函数内层函数可以访问外层函数的变量
    将内存函数作为外层函数的返回,此内层函数就是闭包函数
  2. 闭包的好处和缺点
    • 优点:
      • 不定义全局变量,也可以让函数持续访问和修改一个外部变量
      • 闭包函数引用的外部变量,是外层函数的内部变量。作用域封闭难以被误操作修改
    • 缺点:额外的内存占用
  3. nonlocal关键字的作用
    在闭包函数(内部函数中)想要修改外部函数的变量值
    需要用nonlocal声明这个外部变量

二、装饰器

在编程中,装饰器(Decorator)是一种可以用于修改或扩展函数、方法或类行为的特殊语法。装饰器允许在不修改源代码的情况下,动态地添加或修改函数的功能。在许多编程语言中,装饰器通常以 @ 符号加上装饰器函数或类的形式使用。

下面是一个简单的 Python 装饰器的例子:

def my_decorator(func):def wrapper():print("Something is happening before the function is called.")func()print("Something is happening after the function is called.")return wrapper@my_decorator
def say_hello():print("Hello!")# 调用被装饰的函数
say_hello()

在这个例子中,my_decorator 是一个装饰器函数,它接受一个函数作为参数,并返回一个新的函数 wrapper。通过使用 @my_decorator 语法,我们将 say_hello 函数传递给装饰器,从而将它装饰起来。当调用 say_hello() 时,实际上是调用了装饰后的 wrapper 函数,从而实现了在函数执行前后添加额外功能的效果。

Python 中还有一些内置的装饰器,例如 @property@staticmethod@classmethod 等,它们用于定义属性、静态方法和类方法。同时,Python 也支持同时应用多个装饰器,它们按照从上到下的顺序进行嵌套。

装饰器在代码重用和模块化方面提供了一种灵活而强大的机制,它使得我们可以通过简单地添加装饰器来改变函数或类的行为,而不必修改其原始实现。

装饰器的作用和用法

装饰器其实也是一种闭包, 其功能就是在不破坏目标函数原有的代码和功能的前提下,为目标函数增加新功能。

装饰器的一般写法(闭包写法)

在这里插入图片描述

装饰器的语法糖写法

在这里插入图片描述

代码

"""
演示装饰器的写法
"""# 装饰器的一般写法(闭包)
# def outer(func):
#     def inner():
#         print("我睡觉了")
#         func()
#         print("我起床了")
#
#     return inner
#
# def sleep():
#     import random
#     import time
#     print("睡眠中......")
#     time.sleep(random.randint(1, 5))
#
# fn = outer(sleep)
# fn()# 装饰器的快捷写法(语法糖)
def outer(func):def inner():print("我睡觉了")func()print("我起床了")return inner@outer
def sleep():import randomimport timeprint("睡眠中......")time.sleep(random.randint(1, 5))sleep()

总结

  1. 什么是装饰器
    装饰器就是使用创建一个闭包函数,在闭包函数内调用目标函数。
    可以达到不改动目标函数的同时,增加额外的功能。
  2. 装饰器的写法
    在这里插入图片描述

补充:语法糖

语法糖(Syntactic Sugar)是指一种编程语言的语法特性,它并不提供新的功能,而是用更简洁、更易读的语法形式来表达已有的语法结构。语法糖的目的是提高代码的可读性和易用性,使得开发者能够更加方便地书写和理解代码。

以下是一些编程语言中常见的语法糖例子:

  1. 列表推导式(List Comprehensions):

    # 传统方式
    squares = []
    for x in range(10):squares.append(x**2)# 使用列表推导式
    squares = [x**2 for x in range(10)]
    
  2. 条件表达式(Ternary Operator):

    # 传统方式
    if x > 0:y = 1
    else:y = 0# 使用条件表达式
    y = 1 if x > 0 else 0
    
  3. 匿名函数(Lambda Expressions):

    # 传统方式
    def square(x):return x**2# 使用匿名函数
    square = lambda x: x**2
    
  4. 解构赋值(Destructuring Assignment):

    # 传统方式
    x = (1, 2, 3)
    a = x[0]
    b = x[1]
    c = x[2]# 使用解构赋值
    a, b, c = (1, 2, 3)
    
  5. 字符串格式化(String Formatting):

    # 传统方式
    name = "Alice"
    age = 30
    message = "Hello, {}! You are {} years old.".format(name, age)# 使用字符串格式化语法糖
    message = f"Hello, {name}! You are {age} years old."
    

语法糖并不是一种新的语言特性,而是对已有特性的更友好的表达方式。它使得代码更加简洁、清晰,提高了开发效率。然而,使用语法糖时也需要注意不要过度使用,以免影响代码的可读性。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/300316.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

盘古信息IMS-MOM制造运营管理系统,构建生产现场管理信息系统的最佳选择

在当今高度竞争的制造行业中&#xff0c;高效的生产管理是企业成功的关键。盘古信息IMS-MOM制造运营管理系统作为一款领先的管理系统其关键特性为制造企业构建生产现场管理信息系统提供了强大的优势。IMS-MOM不仅仅是一个软件系统&#xff0c;更是一种技术和管理手段的结合&…

CentOS系统环境搭建(二十六)——使用nginx在无域名情况下使用免费证书设置https

centos系统环境搭建专栏&#x1f517;点击跳转 文章目录 使用nginx在无域名情况下使用免费证书设置https1.获取SSL证书1.1 生成SSL密钥1.2 生成SSL证书1.3 重命名密钥文件 2.nginx配置https2.1 放证书2.2 修改nginx.conf文件2.2.1 将80端口重定向到4432.2.2 端口443配置ssl证书…

DolphinScheduler 介绍及系统架构

目录 一、DolphinScheduler 介绍 1.1 关于 DolphinScheduler 1.2 特性 简单易用 丰富的使用场景 High Reliability High Scalability 1.3 名词解释 1.3.1 名词解释 1.3.2 模块介绍 二、DolphinScheduler 系统架构 2.1 系统架构图 2.2 架构说明 MasterServer 该服…

听GPT 讲Rust源代码--src/tools(27)

File: rust/src/tools/clippy/clippy_lints/src/methods/suspicious_to_owned.rs 文件rust/src/tools/clippy/clippy_lints/src/methods/suspicious_to_owned.rs的作用是实施Clippy lint规则&#xff0c;检测产生潜在性能问题的字符转换代码&#xff0c;并给出相关建议。 在Rus…

IntelliJ IDEA快捷键及调试

文章目录 一、IntelliJ IDEA 常用快捷键一览表1-IDEA的日常快捷键第1组&#xff1a;通用型第2组&#xff1a;提高编写速度&#xff08;上&#xff09;第3组&#xff1a;提高编写速度&#xff08;下&#xff09;第4组&#xff1a;类结构、查找和查看源码第5组&#xff1a;查找、…

[C/C++]数据结构 希尔排序

&#x1f966;前言: 希尔排序也称 “缩小增量排序”&#xff0c;它也是一种插入类排序的方法,在学习希尔排序之前我们首先了解一下直接插入排序. 一: &#x1f6a9;直接插入排序 1.1 &#x1f31f;排序思路 直接插入排序的基本原理是将一条记录插入到已排好的有序表中&#x…

JavaWeb的Servlet的入门和使用方法

1 什么是Servlet Servlet是Server Applet的简称&#xff0c;是用Java编写的是运行在 Web 服务器上的程序&#xff0c;它是作为来自 Web 浏览器或其他 HTTP 客户端的请求和 HTTP 服务器上的数据库或应用程序之间的中间层。使用 Servlet&#xff0c;可以收集来自网页表单的用户输…

【Midjourney】Midjourney提示词格式详解

目录 &#x1f347;&#x1f347;Midjourney是什么&#xff1f; &#x1f349;&#x1f349;Midjourney怎么用&#xff1f; &#x1f514;&#x1f514;Midjourney提示词格式 &#x1f341; 1.模型版本提示词&#x1f341; 参数 参数详解 应用示例 &#x1f343; 2.风格…

【Java中序列化的原理是什么(解析)】

&#x1f341;序列化的原理是什么&#xff1f; &#x1f341;典型-----解析&#x1f341;拓展知识仓&#x1f341;Serializable 和 Externalizable 接门有何不同? &#x1f341;如果序列化后的文件或者原始类被篡改&#xff0c;还能被反序列化吗?&#x1f341;serialVersionU…

【Linux--信号】

目录 一、信号的概念1.1查看系统的信号1.2信号的处理方式 二、信号的产生方式2.1通过终端按键2.2kill命令2.3系统调用2.4软条件产生信号2.5硬件异常产生信号 三、信号的保存3.1概念的认识3.2sigset_t3.3信号集操作函数3.4sigprocmask && sigpending3.4.1sigprocmask3.4…

基于STM32和MQ-2传感器的物联网友好型烟雾报警系统

基于STM32和MQ-2传感器的物联网友好型烟雾报警系统是一种用于检测室内烟雾并及时报警的智能设备。本系统利用STM32微控制器作为主控制单元&#xff0c;通过MQ-2传感器实时监测室内烟雾浓度&#xff0c;并通过无线通信模块将数据传输到云端服务器&#xff0c;实现远程监控和报警…

k8s 组件

k8s: kubernets:8个字母省略&#xff0c;就是k8s. 自动部署&#xff0c;自动扩展和管理容器化的应用程序的一个开源系统。 k8s是负责自动化运维管理多个容器化程序的集群&#xff0c;是一个功能强大的容器编排工具。 以分布式和集群化的方式进行容器管理。 1.20面试版本 …