python闭包函数、装饰器、生成器

1. 闭包函数

什么是闭包函数

闭包函数就是在函数内部定义了一个函数(内嵌函数),并将这个函数的引用作为返回值返回。

但是闭包函数可以调用外部函数的形参和变量,并且在外部调用闭包函数时,其外部函数的形参和变量仍然生效

无参数的闭包函数

def out_func():print("外面的函数被调用") # 1def inner_func():print("里面的函数被调用 -- inner_func()") # 3print("外面的函数调用完成,返回inner_func的引用") # 2return inner_func# out_func()的返回值是inner_func
x = out_func()
# x == inner_func
x()  
print(type(x))# 执行结果
外面的函数被调用
外面的函数调用完成,返回inner_func的引用
里面的函数被调用 -- inner_func()
<class 'function'>

有参数的闭包函数

在调用外部函数时,闭包函数不会被执行,但是外部函数的变量和形参会被放入内存中,当外部调用闭包函数时,闭包函数仍然可以调用内存中其外部函数的形参和变量

def func_out(num1: int):a = 50def func_inner(num2: int):result = num1 + num2 + aprint(f"外部函数的形参为{num1},内部函数的形参为{num2},外部函数的局部变量为{a},相加为{result}")return func_inner  # 注意不能加()f = func_out(100) # 参数 100 是外部函数的传参num1
# 参数 200 是闭包函数的传参num2,因为此时f为func_inner
f(200)# 运行结果外部函数的形参为100,内部函数的形参为200,外部函数的局部变量为50,相加为350

2. 装饰器

什么是装饰器

装饰器本质就是一个闭包函数,它将装饰起来的函数当做参数传递到外部函数的形参,然后在其闭包函数中执行该函数。

装饰器的作用就是在被装饰函数的前后添加新的功能或限制。

无参数的装饰器

如果被装饰的函数带有参数,则需要在闭包函数中添加相应的形参,并在调用被装饰的函数时,将其传递进去

# 装饰器就是一个函数,它会返回一个函数的引用,并且形参有且只有一个
# 装饰器不会改变原函数的功能,它会在其外部(执行前或执行后)添加新的功能或限制
# 装饰器的本质就是一个闭包函数,只是把外部函数的传参是一个函数的引用,在内部函数调用了该函数def check(func):def inner():print("开始登录")print("输入用户名和密码并登录")print("登录中...")print("登录成功")func()return innerdef check2(func):def inner(a):print("开始登录")print("输入用户名和密码并登录")print("登录中...")print("登录成功")func(a)return inner# 1. 可以使用注解的方式添加装饰器
@check
def shopping():print("添加一件商品到购物车")@check2
def shopping2(a):print(f"添加{a}件商品到购物车")# 2. 将原有函数的引用指向装饰器的引用,并将原有函数的引用传递到形参中
# 如果不加装饰器,则需要下面这行代码才能运行shopping()
# shopping2(2)也是同理
# shopping = check(shopping) 
shopping()
shopping2(2)

有参数的装饰器

有参数的装饰器就是在无参数装饰器的基础上再套一层函数,用于将装饰器的参数传递进来,也就是三层函数。

因为第三层的函数需要装饰器的传参,但是第二层的函数的形参需要传递函数引用,所以在第三层函数传递装饰器的传参,然后返回第二层函数,这样第二次函数可以调用第三层函数的形参,也就是装饰器的传参,然后第二层装饰再返回最里面的闭包函数。

这样闭包函数既有装饰器的传参,也有被装饰的函数的引用

def mark(flag):def out_func(fn):def inner_func(num1, num2):print("开始计算...")print("计算完成,结果为:")print(fn(num1, num2))return inner_funcreturn out_func@mark('+')
def add(a, b):return a + b@mark('-')
def sub(a, b):return a - b# 如果不加装饰器则需要执行下面两行代码才能执行add(1, 2)
# sub(1, 2)也是同理
# out_func = mark()
# add = out_func(add)add(1, 2)
sub(1, 2)

3. 生成器

什么是生成器

当一个函数是用来yield关键字时,它就是一个生成器

当生成器执行到yield时会跳出函数(可以返回数据),当下次再调用生成器时,会从上次调用的yield下面一行代码开始运行,直到遇到下一个yield,以此类推

当生成器的内容全部执行完毕之后,想要再次执行生成器需要重新赋值变量

生成器的使用

# 当函数中使用yield关键字时,该函数就是一个生成器
# yield的功能和return一样,可以结束函数的运行,并可以返回值# yield和return的区别,当函数执行yield之后会退出函数,但是下次再调用该函数时会从上传调用yield的下面开始执行def func1():print(1)print(2)print(3)print(4)print(5)yield 6print(7)print(8)print(9)yield 10print(11)print(12)print(13)yield"""使用方法:1. 首先将函数赋值给一个变量fn2. 将变量fn传入到next()函数的形参 --> next(fn)3. 调用next(fn)就相当于调用生成器4. 当生成器内容完全执行完后,该变量不会重新开始生成器的内容
"""fn = func1()
print("第一次调用生成器")
print(f"生成器返回值:{next(fn)}")
print("第二次调用生成器")
print(f"生成器返回值:{next(fn)}")
print("第三次调用生成器")
print(f"生成器返回值:{next(fn)}")print('-' * 100)# 再次调用需要重新赋值
fn1 = func1()
print("第一次调用生成器")
print(f"生成器返回值:{next(fn1)}")
print("第二次调用生成器")
print(f"生成器返回值:{next(fn1)}")
print("第三次调用生成器")
print(f"生成器返回值:{next(fn1)}")
def func2():i = 0while i < 10000:if i == 3000:yield ii += 1yield ifn2 = func2()
print(next(fn2))
print(next(fn2))

yield和return的区别

相同点:yield的功能和return一样,可以结束函数的运行,并且可以返回值。

区别:yield调用后退出函数,下次调用函数时,会从yield下面开始执行函数,return退出后会从头开始执行函数。

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

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

相关文章

基于蝗虫优化的KNN分类特征选择算法的matlab仿真

目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.本算法原理 4.1 KNN分类器基本原理 4.2 特征选择的重要性 4.3 蝗虫优化算法&#xff08;GOA&#xff09; 5.完整程序 1.程序功能描述 基于蝗虫优化的KNN分类特征选择算法。使用蝗虫优化算法&#xff…

C++入门语法———命名空间,缺省参数,重载函数

文章目录 一.命名空间1.存在意义2.语法使用1.定义命名空间2.使用命名空间的三种方式 二.缺省参数1.全缺省参数2.半缺省参数 三.重载函数1.定义2.重载原理———名字修饰 一.命名空间 1.存在意义 C命名空间的主要意义是为了避免命名冲突&#xff0c;尤其是在大型项目中可能存在…

“高级SPA项目构建与路由实现“

目录 引言1. SPA项目构建1.1 安装vue-cli,webpack1.2 创建 Vue.js项目1.3 “一问一答”模式1.4 启动项目 2. SPA项目完成路由3. 基于SPA项目完成嵌套路由总结 引言 在现代Web开发中&#xff0c;单页应用&#xff08;SPA&#xff09;已经成为一种流行的开发模式。SPA通过在前端…

(BUUCTF)0ctf_2018_heapstorm2

文章目录 前置知识整体思路house of storm如何进行一次house of stormhouse of storm原理house of storm具体流程 chunk shrink exp 前置知识 unsortedbin attacklargebin attackoff by null构造chunk shrink 整体思路 这道题即是house of storm。除了house of storm&#x…

优优嗨聚:美团代运营服务,为商家赋能,打造流量转化的秘密武器

随着互联网的飞速发展&#xff0c;人们越来越依赖线上平台进行消费。作为国内领先的电商平台之一&#xff0c;美团吸引了众多商家入驻。然而&#xff0c;如何在竞争激烈的美团平台上脱颖而出&#xff0c;成为了商家们面临的一大挑战。此时&#xff0c;美团代运营服务应运而生&a…

html 粒子效果文字特效

有两个代码如下&#xff1a; index.html <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns"http://www.w3.org/1999/xhtml"> <head>…

HTML5和CSS3的新特性

HTML5的新特性主要是针对于以前的不足&#xff0c;增加了一些新的标签、新的表单和新的表单属性等 1&#xff0c;HTML5新增的语义化标签 <header> 头部标签 <nav> 导航标签 <article> …

《WebKit 技术内幕》学习之九(4): JavaScript引擎

4 实践——高效的JavaScript代码 4.1 编程方式 关于如何使用JavaScript语言来编写高效的代码&#xff0c;有很多铺天盖地的经验分享&#xff0c;以及很多特别好的建议&#xff0c;读者可以搜索相关的词条&#xff0c;就能获得一些你可能需要的结果。同时&#xff0c;本节希望…

记录centos安装nginx过程和问题

今天在centos上安装了nginx&#xff0c;遇到了些问题&#xff0c;记录一下。 使用yum直接安装的话安装的版本是1.20.1&#xff0c;使用源码包安装可以装到1.25.0&#xff08;最新稳定版&#xff09;。很有意思的一点是两种安装方法下安装的路径是不同的&#xff0c;且源码安装…

第一讲:入门知识笔记

python 变量无类型&#xff0c;但值里面有类型。 动态类型语言&#xff08;python&javascript&#xff09;Subtraction num 10 print(num / 2, num // 3, num // -3) # 5.0, 3, -4 向下取整 int(num / 3) # 不用向下取整的办法reverse 3-digit number def res(num):digi…

Java 面向对象案例 03(黑马)

代码&#xff1a; public class phoneTest {public static void main(String[] args) {phone [] arr new phone[3];phone p1 new phone("华为",6999,"白色");phone p2 new phone("vivo",4999,"蓝色");phone p3 new phone("苹…

手把手教你用深度学习做物体检测(一): 快速感受物体检测的酷炫

我们先来看看什么是物体检测&#xff0c;见下图&#xff1a; 如上图所示&#xff0c; 物体检测就是需要检测出图像中有哪些目标物体&#xff0c;并且框出其在图像中的位置。 本篇文章&#xff0c;我将会介绍如何利用训练好的物体检测模型来快速实现上图的效果&#xff0c;这里…

Pyside6中QTableWidget使用

目录 一&#xff1a;介绍&#xff1a; 二&#xff1a;演示 一&#xff1a;介绍&#xff1a; 在 PySide6 中&#xff0c;QTableWidget 是一个用于展示和编辑表格数据的控件。它提供了在窗口中创建和显示表格的功能&#xff0c;并允许用户通过单元格来编辑数据。 要使用 QTabl…

什么是功能测试?原因、方式和类型

功能测试是软件开发和部署之间的检查点。每次点击和每次交互都需要严格的功能测试过程。这不仅仅是为了识别错误&#xff0c;更是为了确保无缝、以用户为中心的体验。完善您的方法并提供功能强大、令人印象深刻且吸引人的软件所需的见解。 什么是功能测试 首先&#xff0c;功能…

多线程批量同步数据到ES

需求背景&#xff1a;新增了ES&#xff0c;现在要讲数据库某张表的数据同步到ES中&#xff0c;百万级的数据量一次性读取同步肯定不行&#xff0c;所以可以用多线程同步执行同步数据。 1.线程池配置类 Configuration public class ThreadPoolConfig {/*** 核心线程池大小*/pr…

C语言学习(5)—— 数组

一、一维数组 1. 基本数据类型的数组 数组的定义&#xff1a;数据类型 数组名 [数组大小]; 数组名就代表该数组的首地址&#xff0c;即a[0]的地址 使用下标来访问数组元素 数组是多个相同类型数据的组合&#xff0c;一个数组一旦定义了&#xff0c;其长度是固定的&…

开源模型应用落地-业务整合篇(四)

一、前言 通过学习第三篇文章,我们已经成功地建立了IM与AI服务之间的数据链路。然而,我们目前面临一个紧迫需要解决的安全性问题,即非法用户可能会通过获取WebSocket的连接信息,顺利地连接到我们的服务。这不仅占用了大量的无效连接和资源,还对业务数据带来了潜在的风险。…

build.gradle标签详解

一、简介 Gradle是一个开源的构建自动化工具&#xff0c;主要用于Java、Groovy和其他JVM语言的项目。它使用一个基于Groovy或Kotlin的特定领域语言(DSL)来声明项目设置&#xff0c;从而摒弃了基于XML的繁琐配置。build.gradle是Gradle项目的核心配置文件&#xff0c;它定义了项…

系统架构设计师教程(十五)面向服务架构设计理论与实践

面向服务架构设计理论与实 15.1 SOA的相关概念15.1.1 SOA的定义15.1.2 业务流程与BPEL15.2 SOA的发展历史15.2.1 SOA的发展历史15.2.2 国内SOA的发展现状与国外对比15.2.3 SOA的微服务化发展15.3 SOA的参考架构15.4 SOA主要协议和规范15.4.1 UDDI协议15.4.2 WSDL规范15.4.3 SOA…