news 2026/4/16 19:56:43

Python推导式与闭包全解析

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Python推导式与闭包全解析

一,推导式

定义:用一句简洁的语句,从迭代对象中,生成新列表的语法结构(对for循环+append()的一种简写形式)

语法:[表达式 for 变量 in 可迭代对象]

1.列表推导式

这是for循环+append num=[1,2,3,4,5]res=[]foriinnum:res.append(i*2)print(res)推导式 num=[1,2,3,4,5]res=[n*2forninnum]print(res)带条件的推导式 num=[1,2,3,4,5]res=[n*2forninnumifn>2]print(res)


2.字典推导式

name=['张大','张二','张三']score=[70,6,80]res={name[i]:score[i]foriinrange(len(name))}#取下标用下标一一对应print(res)

3.集合推导式

name=['张大','张二','张三']res={i+'?'foriinname}print(res)


没有元组推导式(生成器)

二,内置函数

1.输入与输出

print() 输出指定内容
完整参数:print(*objects, sep=’ ‘, end=’\n’,file=sys.stdout, flush=False)
参数详解:
1.objects:要输出的内容
2.sep:分隔符
3.end:结束符
4.file:输出位置
5.flush:是否立即刷新

importtimeforindexinrange(1,101):print(f'\r已加载{index}%',end='',flush=True)time.sleep(0.1)

一个加载

input() 获取用户输入

2.类型转换

int() 转为整数
float() 转为浮点数
str()转为字符串
bool() 转为布尔值
list() 转为列表
tuple() 转为元组
set() 转为集合
dict() 转为字典

3.数学相关

abs() 取绝对值

print(abs(-9))print(abs(-2.5))print(abs(3-5))#正负都可以

round() 四舍五入
注意:round函数的四舍五入,是银行家舍入法:小于5就舍,大于5就入,等于5看奇偶(奇入偶舍)

pow() 次方

#正负都可以 print(pow(2, 3)) # 2的3次方 print(pow(2, -1)) # 2的-1次方 print(pow(2, 0.5)) # 2的开平方 print(pow(2, 3, 5)) # 2的3次方对5取模

divmod() 商和余数

print(divmod(10,3))#结果为(3,1)

max() 最大值(支持 key 函数)
min() 最小值(支持 key 函数)
sum() 求和
map() 加工一组数据
filter() 按条件过滤数据(支持 key 函数)
reduce() 合并计算(需导入 functools)
sorted() 排序(支持 key 函数)

4.数据容器相关

len() 获取容器中元素的个数
range() 生成一个数字序列(可用于循环)

forindexinrange(0,10,2):#2相当于步长print(index)

enumerate() 给序列添加索引
zip() 将多个序列一一配对(以少的为准你可以少写)

names=('张三','李四','王五')scores=[60,70,80]res=zip(names,scores)print(list(res))

5.类型判断与对象相关

type() 查看类型
isinstance()判断类型
issubclass() 判断两个类的继承关系
id()查看对象的内存地址

六、逻辑判断相关

all() 全为真返回True any() 有一个为真即可
any() ====> 有一个为真即可

l=[0,'',None,False,1]print(any(l))

7.字符串辅助相关

ord() 获取字符的 Unicode 编码值
chr() 将 Unicode 编码值转为字符

三,拷贝

1.浅拷贝

定义:创建一个新的外层容器,但是内部元素仍然引用原来的对象
注意:嵌套数据仍然共享,修改嵌套数据会相互影响

importcopy#需要加代码块num=[1,2,3,4,5,[1,2,3]]nums=copy.copy(num)nums[5][1]=10print(nums)print(num)

2.深拷贝

定义:创建一个新的外层容器,并对其内部所有的可变对象进行递归复制

注意:
1.深拷贝只复制可变对象,不可变对象直接引用
2.元组中如果只包含不可变对象则深拷贝无效

importcopy num=[1,2,3,4,5,[1,2,3]]nums=copy.deepcopy(num)nums[5][1]=10print(nums)print(num)

四,四种作用域

查找顺序是局部作用域>外层作用域>全局作用域>内建作用域

1.局部作用域(local)

定义:函数内部是局部作用域,局部作用域中的变量,只能在函数内部可见 特点:
1.每次调用函数都会创建一个新的局部作用域
2.函数运行结束后,局部作用域之后就会销毁
3.局部作用域优先级最高

2.外层作用域(encolosing)

定义:如果函数中又定义了图数,那么外展的数的作用域,就是内层函数的 Enclosing 作用域 特点:
1.只有当函数,嵌套定义”时才会出现。
2.内层函数可以读取外层函数交量。
3.想修改外层变量必须使用nonlocal

3.全局作用域(global)

定义:.py 文件就是全局作用域,全局作用城中的变量,在当前.py文件的任何位置都可以访问. 特点:
1.全局变量只在当前.py 文件中可见。
2.函数内部可以使用global关键字作改全受量

4.内建作用域(built-in)

定义:Python 预先定义好的东西,会放在内建作用域中所有.py文件都可以直接使用,
特点:
1.所有 .py文件都能直接使用其中的名称
2.例子:print len range
3.查找此先级册低(LEGB的B)

a=100#全局作用域deftest(b):print('我是test函数')#外层函数作用域print('test中打印的a是',a)print('test收到的参数b是',b)c=200d=300print('test中的c和d是',c,d)definner():#局部作用域e=400nonlocalc c=999print('inner中的e是',e)print('inner中打印的c是',c)print('###',a)inner()print('??',c)print('全局打印的a是',a)test(66)

五,闭包

定义:闭包=内层函数+被内层函数所引用的外层变量

产生条件:
1.有函数嵌套
2.在内层函数中,要访问外层函数的变量(没有用到的就会被销毁)
3.并且外层函数要返回内层函数这样才不会在局部变量中被销毁

defouter():num=10definner():nonlocalnum num+=1print(num)returninner f=outer()f()f()f()

结论:
1.outer函数中,被inner所使用到的那些变量,会被封存到闭包单元(cell)中。
2.这些 cell 会组成一个closure元组,最终放在了 inner 函数身上。
注意:
1.调用n次外层函数,就会得到n个不同的闭包,并且这些闭包之间互不影响
2.内层函数中用到的外层变量是可变对象,多个闭包之间依然互不影响
优点:

  1. 可以“记住”状态:不用全局变量,也不用写类,就能在多次调用之间保存数据。
  2. 可以做“配置过的函数”:先传一部分参数,把环境固定住,得到一个定制版函数。
  3. 可以实现简单的“数据隐藏”:外层变量对外不可见,只能通过内层函数访问。
  4. 是装饰器(decorator)等高级用法的基础。
defbeauty(char,n):defshow_msg(msg):print(char*n+msg+char*n)returnshow_msg show1=beauty('*',2)show1('你好')show1('直立千古')show2=beauty('@',2)show2('你好')show2('水宕骑虎')

缺点:

  1. 理解成本较高:对初学者不太友好,滥用会让代码难读。
  2. 如果闭包里引用了很大的对象,又长期不释放,可能会增加内存占用。
  3. 很多场景下,其实用【类 + 实例属性】会更清晰,闭包不一定是最优解。

六,装饰器

1. 函数装饰器

定义:
1.装饰器是一种【可调用对象】(通常是函数),它能接收一个函数作为参数,并且会返回一个新函数。
2.装饰器可以在不修改原函数代码的前提下,增强或改变原函数的功能。

实际应用:在不改变原函数的前提下,给函数统一加上:日志、计时、校验、缓存 等功能

关键点:
1.接收被装饰的函数、同时返回新函数(wrapper)
2.装饰器“吐出来”的是 wrapper 函数,以后别人调用的也是 wrapper 函数。
3.为了保证参数的兼容性,wrapper 函数要通过 *args 和 **kwargs 接收参数。
4.wrapper 函数中主要做的是:调用原函数(被装饰的函数)、执行其它逻辑,但要记得将原函数的返回值 return 出去。

手动装饰

defsay(func):defwrapper(*args,**kwargs):print('你好,我要开始计算了')returnfunc(*args,**kwargs)returnwrapperdefadd(x,y,z):res=x+y+zprint(f'{x}{y}{z}相加的结果是:{res}')returnres add=say(add)result=add(10,20,30)print(result)

使用装饰器

defsay(func):defwrapper(*args,**kwargs):print('你好,我要开始计算了')returnfunc(*args,**kwargs)returnwrapper#@saydefadd(x,y,z):res=x+y+zprint(f'{x}{y}{z}相加的结果是:{res}')returnres# 正常调用add函数result=add(10,20,30)print(result)


带参数的装饰器(三层嵌套,外层接收配置、中间层接收函数、内层接收具体参数)

defsay(msg):defouter(func):defwrapper(*args,**kwargs):print(f'你好,我要开始{msg}计算了')returnfunc(*args,**kwargs)returnwrapperreturnouter@say('加法')defadd(x,y,z):res=x+y+zprint(f'{x}{y}{z}相加的结果是:{res}')returnres@say('减法')defsub(x,y):res=x-yprint(f'{x}{y}相减的结果是:{res}')returnres result1=add(10,20,30)print(result1)result2=sub(20,10)print(result2)


多个装饰器一起使用

deftest1(func):print('我是test1装饰器')defwrapper(*args,**kwargs):res=func(*args,**kwargs)print('test1追加的逻辑')returnresreturnwrapperdeftest2(func):print('我是test2装饰器')defwrapper(*args,**kwargs):res=func(*args,**kwargs)print('test2追加的逻辑')returnresreturnwrapper@test1@test2defadd(x,y):res=x+yprint(f'{x}{y}相加的结果是{res}')returnres result=add(10,20)

这个输出结果相当于add =test1(test2(add))从外向内后面因为先运行的res = func(*args, **kwargs)所以他会加在add函数输出结果的下面,因为后进先出所以add结果先出来了

2.类装饰器

1.包含call方法的类,就是类装饰器。
2.像调用函数一样,去调用类装饰器的实例对象,就会触发call方法的调用。
3.call方法通常接收一个函数作为参数,并且会返回一个新函数。

classSay:def__call__(self,func):defwrapper(*args,**kwargs):print('开始计算了')returnfunc(*args,**kwargs)returnwrapper#使用@语法使用类装饰器@Say()defadd(x,y):res=x+yprint(f'{x}{y}相加的结果是{res}')returnres result=add(10,20)print(result)

带参数的类装饰器

classSay:def__init__(self,msg):self.msg=msgdef__call__(self,func):defwrapper(*args,**kwargs):print(f'开始{self.msg}计算了')returnfunc(*args,**kwargs)returnwrapper@Say('加法')defadd(x,y):res=x+yprint(f'{x}{y}相加的结果是{res}')returnres result=add(10,20)print(result)

多个类装饰器的使用

classTest1:def__call__(self,func):defwrapper(*args,**kwargs):print('我是Test1的逻辑')returnfunc(*args,**kwargs)returnwrapperclassTest2:def__call__(self,func):defwrapper(*args,**kwargs):print('我是Test2的逻辑')returnfunc(*args,**kwargs)returnwrapper@Test1()@Test2()defadd(x,y):res=x+yprint(f'{x}{y}相加的结果是{res}')returnres result=add(10,20)print(result)

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/16 2:23:25

Conductor微服务编排引擎终极实战指南:从入门到精通

Conductor微服务编排引擎终极实战指南:从入门到精通 【免费下载链接】conductor Conductor is a microservices orchestration engine. 项目地址: https://gitcode.com/GitHub_Trending/co/conductor 微服务编排引擎Conductor是Netflix开源的核心项目&#x…

作者头像 李华
网站建设 2026/4/16 13:01:20

常用的 SQL 语句分类及其语法:

好的,以下是常用的 SQL 语句分类及其语法:1. 数据查询 (SELECT)基本查询:SELECT 列名1, 列名2, ... FROM 表名;查询所有列:SELECT * FROM 表名;查询表数据:SELECT COUNT(*) FROM 表名带条件查询 (WHERE):SE…

作者头像 李华
网站建设 2026/4/16 12:55:35

ECM CCCM

✅ ECM19.0 中的 CCCM:跨分量相关模型详解 在 VVC(H.266) 的实验参考模型 ECM(Experimental Common Model)19.0 中,CCCM(Cross-Component Correlation Model) 是一项关键的屏幕内容编…

作者头像 李华
网站建设 2026/4/15 16:20:52

Cuda Rudece算子实现(附4090/h100测试)

1.Ruduce/规约 定义 对整个张量进行一个操作,得到一个标量结果。这个操作可以是max,min,summax,min,summax,min,sum等。 2.原理 我们用单线程的思路来实现的话,就是遍历整个张量,然后来做reducereducereduce的操作即可。 for(int i 0; i…

作者头像 李华
网站建设 2026/4/16 0:13:43

83、深入探索 Linux 云部署与配置

深入探索 Linux 云部署与配置 1. Linux 云基础配置 Linux 云的基础配置主要在 /etc/cloud/cloud.cfg 文件中完成。在此文件里,默认情况下 root 用户账户是禁用的。文件底部显示,名为 fedora 的用户是默认用户,且拥有无需密码的 sudo 权限。以下是该文件的部分内容: …

作者头像 李华