【Python】python系列之函数闭包概念

【Python】python系列之函数闭包概念

目录

一、函数

二、闭包

2.1 概念

2.2闭包的应用场景

2.3代码实例

实例 1:简单计数器闭包

实例 2:带参数的闭包

实例 3:闭包用于数据封装和隐藏


一、函数


函数是实现特定功能的代码段的封装,在需要时可以多次调用函数来实现该功能。

Python如下定义一个函数,我们可以通过任何变量来将此函数进行赋值操作,如下:

def greet(): return "Hello!" # 将方法赋给变量(无括号,得到方法对象) greet_func = greet # 调用存储在变量中的方法 print(greet_func()) print(type(greet_func)) # 输出 greet_func 的类型,由于 greet_func 指向的是 greet 函数对象,所以输出结果为 <class 'function'> print(type(greet_func())) # 先调用 greet_func 所指向的函数,得到返回值 "Hello!",然后输出该返回值的类型,结果为 <class 'str'>。 # 有括号,直接调用方法并将结果赋给变量 greet_result = greet() print(greet_result) print(type(greet_result)) # 输出 greet_result 的类型,由于它存储的是字符串,所以输出结果为 <class 'str'> print(type(greet_result())) # 报错greet_result 存储的是字符串 "Hello!",而不是函数对象,所以不能像调用函数一样在它后面加上括号 () 

在 Python 中,函数是一等公民,这意味着函数可以像其他对象(如整数、字符串等)一样被赋值给变量。这里将 greet 函数对象赋值给了变量 greet_func。此时 greet_func 实际上指向的是 greet 函数本身,而不是函数的返回值;而 greet_result = greet() 是先调用 greet 方法,然后把返回值赋给 greet_result 变量。


二、闭包


2.1 概念


在 Python 中,闭包(Closure)是一种特殊的函数,它由一个函数和该函数所引用的外部作用域中的变量组成。即使外部函数已经执行完毕,其局部变量的生命周期也会因闭包的存在而得以延长,闭包可以继续访问这些变量。

简单来说,闭包允许函数访问并操作其定义所在的外部作用域中的变量,即使该外部作用域已经结束。

构成闭包需要满足以下三个条件:

  • 存在一个嵌套函数,即在一个函数内部定义另一个函数。
  • 嵌套函数引用了外部函数的局部变量。
  • 外部函数返回嵌套函数。

2.2 闭包的应用场景


  • 数据封装和隐藏:可以将数据隐藏在闭包内部,只通过闭包提供的接口来访问和修改数据。
  • 实现回调函数:在事件驱动编程中,闭包可以作为回调函数,保存一些上下文信息。
  • 实现装饰器:装饰器是闭包的一种常见应用,用于在不修改原函数代码的情况下,为函数添加额外的功能。

2.3 代码实例


实例 1:简单计数器闭包

def outer_function(): # 外部函数的局部变量 count = 0 def inner_function(): # 声明count为外部函数的局部变量, 以便可以修改它 nonlocal count count = count + 1 return count return inner_function # 创建闭包实例 counter = outer_function() # 多次调用闭包 print(counter()) # 输出: 1 print(counter()) # 输出: 2 print(counter()) # 输出: 3

代码解释

  • outer_function是外部函数,它定义了局部变量count并初始化为 0。
  • inner_function是嵌套在outer_function内部的函数,它引用了外部函数的 count 变量,并对其进行加 1 操作。nonlocal 关键字用于告诉 Python,count 变量不是当前inner_function的局部变量,而是外部函数的局部变量,这样才能在内部函数中修改它。
  • outer_function 返回了 inner_function,形成了闭包。当调用 outer_function() 时,会返回inner_function 的引用并赋值给counter。每次调用 counter() 时,count变量的值都会在之前的基础上增加 1,说明 count 变量的状态被闭包保存下来了。

实例 2:带参数的闭包

def multiplier(factor): print("++++++", factor) def multiply_by_factor(number): print("++++++", number) return number * factor return multiply_by_factor # 创建一个乘以 3 的闭包 triple = multiplier(3) # 调用 __closure__ 内置方法可以查看到两个内存地址,结果返回cell就是闭包,None 则不是闭包,可以看出来其实这是一个元组类型,使用[0].cell_contents可以得到闭合数值,也就闭包所需要的环境变量。 print(triple.__closure__) # 闭包所需要的环境变量 print(triple.__closure__[0].cell_contents) print(triple.__class__) print(triple(5))

代码解释

  • multiplier 是外部函数,它接受一个参数 factor
  • multiply_by_factor 是嵌套函数,它接受一个参数 number,并返回 number 乘以 factor 的结果。
  • multiplier 返回 multiply_by_factor,形成闭包。调用 multiplier(2) 会返回一个闭包,该闭包会将传入的数字乘以 2,将其赋值给 double。同理,multiplier(3) 返回的闭包会将传入的数字乘以 3,赋值给 triple

运行结果:


实例 3:闭包用于数据封装和隐藏

def account(initial_balance): balance = initial_balance def deposit(amount): nonlocal balance balance = balance + amount return balance def withdraw(amount): nonlocal balance if amount <= balance: balance = balance - amount return balance else: print("余额不足") return balance def get_balance(): return balance return deposit, withdraw, get_balance # 创建账户闭包 deposited, withdrawed, get_balanceed = account(1000) # 存款操作 print(deposited(500)) # 输出: 1500 # 取款操作 print(withdrawed(200)) # 输出: 1300 # 查询余额 print(get_balanceed()) # 输出: 1300 

代码解释

  • account 是外部函数,它接受一个初始余额 initial_balance 并将其赋值给局部变量 balance
  • deposit、withdrawget_balance 是嵌套函数, 它们 都引用了外 部函数balance 变量。deposit 函数用于存款,withdraw 函数用于取款,get_balance 函数用于查询余额。
  • account 函数返回这三个嵌套函数,形成闭包。通过调用account(1000) 创建了一个账户闭包,并将返回的三个函数分别赋值给 depositedwithdraweget_balanceed。可以通过调用这些函数来进行账户的存款、取款和查询余额操作, 而 balance 变量被封装在闭包内部,外部无法直接访问,实现了数据的封装和隐藏。

参考文章:

python小课堂26 - 进阶必修之闭包(一)

https://zhuanlan.zhihu.com/p/55949749

Read more

微信小程序webview postmessage通信指南

微信小程序webview postmessage通信指南

需求概述 在微信小程序中使用 web-view 组件与内嵌网页进行双向通信,主要通过 postMessage 实现。以下是完整的配置和使用方法: 通信指南 微信小程序webview官方文档 1. 基础配置 小程序端配置 // app.json 或 page.json { "usingComponents": {}, "permission": { "scope.webView": { "desc": "用于网页和小程序通信" } } } 网页端配置 <!-- 内嵌网页需引入微信JS-SDK --> <script src="https://res.wx.qq.com/open/

By Ne0inhk

OpenClaw Webhook 详解:完整指南

Webhook 是将 OpenClaw 从“聊天助手”快速转变为“响应式系统”的最佳方式。无需等待您主动发送消息,GitHub 可以在 PR 提交时通知 OpenClaw,Stripe 可以在支付失败时通知 OpenClaw,n8n 也可以按计划通知 OpenClaw。OpenClaw 会接收这些传入事件,并将其转换为代理运行或轻量级唤醒操作,然后将结果路由回您实际使用的任何渠道。 本文重点介绍 OpenClaw 网关上的 HTTP Webhook。OpenClaw 中还有另一种东西,在一些文档和配置中也被称为“钩子”。这些是网关内部的事件钩子,当本地生命周期事件触发时运行。它们也很有用,但 Stripe 或 GitHub 与服务器通信的方式并非通过它们。 如果您的 OpenClaw 实例是刚刚部署在 VPS 上,并且您仍然使用 SSH 进行基本操作,那么首先要确保网关稳定,

By Ne0inhk
『AI辅助Skill』掌握三大AI设计Skill:前端独立完成产品设计全流程

『AI辅助Skill』掌握三大AI设计Skill:前端独立完成产品设计全流程

📣读完这篇文章里你能收获到 1. 🎨 掌握ASCII Design快速验证产品想法的方法 2. 🖼️ 学会Wireframe Design生成专业SVG线稿 3. 💻 了解三种Frontend Design Skills的选择策略 4. 🚀 掌握完整OPC工作流,1-2天完成产品开发 文章目录 * 前言 * 一、三大AI设计Skill工作流 * 1.1 传统流程的核心痛点 * 1.2 AI辅助工作流 * 二、ASCII与Wireframe设计技能 * 2.1 ASCII Design Skill —— 秒级验证产品想法 * 2.2 Wireframe Design Skill —— 专业级设计原型 * ASCII vs SVG:如何选择 * 核心特性 * 工作流程 * 三、Frontend Design Skills选择策略 * 3.1

By Ne0inhk
唤醒80年代记忆:基于百度地图的一次老式天气预报的WebGIS构建之旅

唤醒80年代记忆:基于百度地图的一次老式天气预报的WebGIS构建之旅

目录 一、省会城市信息构建 1、省会城市空间查询 2、Java后台查询 二、Java省会城市天气查询 1、与百度开放平台集成天气 2、响应对象属性介绍 3、省会天气实况展示 三、WebGIS应用构建 1、背景音乐集成 2、城市标记及天气展示 3、城市轮播 4、成果展示 四、总结 前言         在数字技术飞速发展的今天,我们常常沉浸于各种高科技带来的便捷与震撼之中,却容易忽视那些曾经陪伴我们成长、承载着时代记忆的旧事物。80年代的天气预报,便是这样一份珍贵的文化遗产。它以简洁而质朴的方式,传递着天气信息,也传递着那个时代的气息。那种对自然的敬畏、对信息的渴望,以及一家人共同分享的温馨氛围,都深深烙印在我们的记忆中。然而,随着时间的推移,天气预报的形式已经发生了翻天覆地的变化。高清的画面、精准的数据、个性化的推送……这些现代技术带来的便利固然令人欣喜,但也在一定程度上让我们失去了那份对天气预报本身的纯粹情感。于是,

By Ne0inhk