Python程序设计 闭包

1. 闭包

1.1 作用域

  • 内置名称(built-in names), Python 语言内置的名称,比如函数名 abs、char 和异常名称 BaseException、Exception 等等。
  • 全局名称(global names),模块中定义的名称,记录了模块的变量,包括函数、类、其它导入的模块、模块级的变量和常量。
  • 局部名称(local names),函数中定义的名称,记录了函数的变量,包括函数的参数和局部定义的变量。(类中定义的也是)

作用域是程序运行时变量可被访问的范围,定义在函数内的变量是局部变量,局部变量的作用范围只能是函数内部范围内,它不能在函数外引用。

def foo():num = 10  # 局部变量print(num)  # NameError: name 'num' is not defined

定义在模块最外层的变量是全局变量,它是全局范围内可见的,当然在函数里面也可以读取到全局变量的。例如:

num = 10  # 全局变量def foo():print(num)  # 10

1.2 嵌套函数

函数不仅可以定义在模块的最外层,还可以定义在另外一个函数的内部,像这种定义在函数里面的函数称之为**嵌套函数**(nested function)例如:

def print_msg():# print_msg 是外围函数msg = 10def printer():# printer是嵌套函数print(msg)printer()# 输出
print_msg()

对于嵌套函数,它可以访问到其外层作用域中声明的非局部(non-local)变量,比如代码示例中的变量 msg 可以被嵌套函数 printer 正常访问。

那么有没有一种可能即使脱离了函数本身的作用范围,局部变量还可以被访问得到呢?答案是闭包

1.3 global 和 nonlocal关键字

当内部作用域想修改外部作用域的变量时,就要用到 global 和 nonlocal 关键字了。

global 用于声明全局变量, nonlocal 用于闭包向上查找变量

1.4 什么是闭包

闭包就是能够读取其他函数内部变量的函数, 由于在 Python 语言中,只有函数内部的子函数才能读取局部变量, 因此可以把闭包简单理解成 “定义在一个函数内部的函数”。 所以,在本质上,闭包就是将函数内部和函数外部连接起来的一座桥梁。

闭包的用途:

  • 可以在函数外部读取函数内部成员
  • 让函数内成员始终存活在内存中

函数身为第一类对象,它可以作为函数的返回值返回,现在我们来考虑如下的例子:

def foo():"""闭包有自己的环境"""num = random.randint(1, 10)def printer():return numreturn printer# 把函数当做变量使用
pri = foo()
print('pri', pri())
print('pri', pri())

不同的地方在于内部函数 printer 直接作为返回值返回了。

一般情况下,函数中的局部变量仅在函数的执行期间可用,一旦 print_msg() 执行过后,我们会认为 msg变量将不再可用。然而,在这里我们发现 print_msg 执行完之后,在调用 foo 的时候 num 变量的值就返回了,这就是闭包的作用,闭包使得局部变量在函数外被访问成为可能。

看完这个例子,我们再来定义闭包,维基百科上的解释是:

在计算机科学中,闭包(Closure)是词法闭包(Lexical Closure)的简称,是引用了自由变量的函数。这个被引用的自由变量将和这个函数一同存在,即使已经离开了创造它的环境也不例外。所以,有另一种说法认为闭包是由函数和与其相关的引用环境组合而成的实体。

闭包,顾名思义,就是一个封闭的包裹,里面包裹着自由变量,就像在类里面定义的属性值一样,自由变量的可见范围随同包裹,哪里可以访问到这个包裹,哪里就可以访问到这个自由变量。 

 

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

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

相关文章

自偏置电流镜、wilson和cascode电流镜、低压自偏置电流镜

1.自偏置电流镜 参考1:正确偏置和自启动电路 正确偏置: 2.自启动电路 参考2:两种自启动电路、cascode低压设计、自启动充放电过程分析 3.低压自偏置电流镜 参考3:电阻偏置分析 VbVgs3VodVgs1Vod 4.电阻偏置和MOS偏置的分…

【C++】动态规划算法

目录 还会持续更新动态规划斐波那契模型三步问题最小花费爬楼梯 路径问题不同路径路径问题Ⅱ 简单多状态按摩师 还会持续更新 动态规划 什么是动态规划? 斐波那契模型 三步问题 class Solution { public: const int N 1000009;int waysToStep(int n) {if(n1) …

Promise 与 async await 的区分同步与异步任务

由于JavaScript负责解释执行的主线程是单线程的,所以如果遇到耗时比较大的任务则会导致后面的任务阻塞。所以将任务分为了异步任务和同步任务,异步任务又被分为宏任务和微任务。异步任务可以解决阻塞的问题但也会带来执行的不确定性。异步任务也叫异步编…

服务器远程桌面连接不上怎么办?

随着互联网的发展和远程办公的兴起,服务器远程桌面连接成为了许多企业和个人不可或缺的工具。偶尔我们可能会碰到服务器远程桌面连接不上的情况,这时候我们需要找到解决办法,确保高效地远程访问服务器。 天联组网——突破远程连接障碍 在我们…

前端二维码工具小程序使用说明书

一、产品概述 前端二维码工具小程序是一款便捷、高效、易用的二维码生成与识别工具。本产品支持根据用户输入的文本或链接生成二维码,同时提供扫一扫功能以识别二维码内容,并支持将识别到的内容复制到剪贴板。此外,产品还提供了美化功能&…

Hadoop生态系统主要是什么?

Hadoop生态系统主要由以下几部分组成: Hadoop HDFS:这是Hadoop的核心组件之一,是一个用于存储大数据的分布式文件系统。它可以在廉价的硬件上提供高度的容错性,通过数据复制和故障切换实现数据的高可用性。 MapReduce&#xff1a…

Armadillo库:用于线性代数和科学计算的快速C/C++库下载及vs环境下的使用方法

armadillo库的下载及使用 一. armadillo库的下载二. vs2022环境下armadillo库的基本使用方法 一. armadillo库的下载 armadillo库的官方下载连接: https://arma.sourceforge.net/download.html 选择网页中最新版本的armadillo库压缩包文件进行下载。 解压armadillo-12.8.2.ta…

无重复的最长字串

📝个人主页:五敷有你 🔥系列专栏:算法分析与设计 ⛺️稳中求进,晒太阳 问题 给定一个字符串,我们需要找到该字符串中的最长无重复子串的长度。 示例 让我们以一个具体的示例来说明这个问题&#…

五_交换网络

交换机是局域网中最重要的设备,用于将同一网络中的多个设备连接起来。交换机基于MAC地址进行工作。本章主要介绍交换原理、转发方法、交换网络层次结构、交换机管理(SSH)和交换机安全等内容。 5.1 交换网络概述 5.1.1 交换机的工作原理 从传统概念来讲…

场景文本检测识别学习 day02(AlexNet论文阅读、ResNet论文精读)

怎么读论文 在第一遍阅读的时候,只需要看题目,摘要和结论,先看题目是不是跟我的方向有关,看摘要是不是用到了我感兴趣的方法,看结论他是怎么解决摘要中提出的问题,或者怎么实现摘要中的方法,然…

Elementplus 2.6.1表单校验模块开发体验改进

需求 之前的表单代码看了下,写的比较冗长,于是去万能的Github找点轮子,发现了这个: GitHub - aweiu/element-ui-verify: 如果你受够了饿了么ElementUI原生的校验方式,那就来试试它吧!一款更懂你的校验插件…

Taro框架中的H5 模板基本搭建

1.H5 模板框架的搭建 一个h5 的基本框架的搭建 基础template 阿乐/H5 Taro 的基础模板

Java多线程实战-从零手搓一个简易线程池(四)线程池生命周期状态流转实现

🏷️个人主页:牵着猫散步的鼠鼠 🏷️系列专栏:Java全栈-专栏 🏷️本系列源码仓库:多线程并发编程学习的多个代码片段(github) 🏷️个人学习笔记,若有缺误,欢迎评论区指正…

nexus设置s3存储

问题 因为我的nexus是安装在EC2上面,需要利用s3的存储能力,为nexus提供存储服务。 步骤 准备s3桶 输入桶名,创建s3桶,如下图: 创建桶读写策略 具体内容如下: {"Version": "2012-10-1…

c++之代码编译问题

为什么头文件不是编译的对象 1、头文件与包含指令(#include) 那些没有被项目中任何源文件包含的头文件,编译器是不去理会它的,不管它有没有语法错误,也不管它是否已添加到项目中。 2、包含指令的执行 包含指令是一种预编译指令,它…

如何区别进化和演化

在生物学中,"进化"和"演化"这两个词通常可以互换使用,它们都指的是生物种群随时间推移而发生的遗传变化。然而,在某些语境中,这两个词可能会有细微的差别: 进化(Evolution)…

Java基础知识总结(46)

(1)构造器 构造器的定义: 需要注意的是构造器是一种特殊的方法,其方法名和类名相同,但没有方法返回值,也不用void修饰。 [修饰符] 方法名(形参列表){ •方法体 •} 修饰符:修饰符可以省略&am…

java中的尾递归

1、基本概念 1)尾调用: 在计算机学里,尾调用是指一个函数里的最后一个动作是返回一个函数的调用结果的情形,即最后一步新调用的返回值直接被当前函数的返回结果。此时,该尾部调用位置被称为尾位置。尾调用中有一种重…

[翻译] 在 CI 或测试环境中使用 Docker-in-Docker,三思而后行

发布日期:2024-04-08 18:01:01 原文地址:Using Docker-in-Docker for your CI or testing environment? Think twice. Docker-in-Docker 的主要目的是帮助 Docker 本身的开发。许多人使用它来运行 CI(例如使用 Jenkins)&#xf…

[NKCTF2024]-PWN:leak解析(中国剩余定理泄露libc地址,汇编覆盖返回地址)

查看保护 查看ida 先放exp 完整exp: from pwn import* from sympy.ntheory.modular import crt context(log_leveldebug,archamd64)while True:pprocess(./leak)ps[101,103,107,109,113,127]p.sendafter(bsecret\n,bytes(ps))cs[0]*6for i in range(6):cs[i]u32(p…