6、python的高级特性(生成式、生成器、闭包、装饰器)
创始人
2024-03-01 11:46:46

文章目录

  • 生成式
    • 列表生成式
    • 字典生成式
    • 集合生成式
  • 生成器
    • 生成器的实现方式
      • 将生成式改写成生成器。将[ ] 改成 ( )
      • 使用yield关键字
  • 闭包
  • 装饰器

生成式

列表生成式

在“先有一个空列表,然后通过循环依次将元素添加到列表中”的场景,可以使用列表生成式。

列表生成式就是一个用来生成列表的特定语法形式的表达式。是python提供的一种生成列表的简洁形式,可以快速生成一个新的列表。

思考如下需求:
需求: 生成100个验证码(4个字母组成的验证码),
平常做法:

import string 
import random
codes=[]
for i in range(100):code="".join(random.sample(string.ascii_letters, 4))codes.append(code)
print(codes)

在这里插入图片描述

使用列表生成式
for循环100次,每次生成的直接加入列表中

import string
import random
codes = ["".join(random.sample(string.ascii_letters, 4)) for i in range(100)]
print(codes)

在这里插入图片描述
考虑需求:
找出1-100之间可以被3整除的数。
平常做法:

nums=[]
for i in range(1,101):if i %3==0:nums.append(i)
print(nums)

使用生成式实现:

nums=[i for i in range(1,101) if i % 3 ==0]
print(nums)

在这里插入图片描述
列表生成式中,for循环可以嵌套if语句,for循环也可以嵌套for循环,但是for循环嵌套for循环代码不太好读。

字典生成式

用来快速生成字典
在“先有一个空字典,然后通过循环依次将元素添加到字典中”的场景,可以使用字典生成式。

dic = {i: i ** 2 for i in range(10)}
print(dic)

在这里插入图片描述

集合生成式

用来快速生成集合

在“先有一个空集合,然后通过循环依次将元素添加到集合中”的场景,可以使用集合生成式。

result = {i ** 2 for i in range(10)}
print(result)

在这里插入图片描述

生成器

  • 在Python中,一边循环一边计算的机制,称为生成器:Generator。
  • 什么时候需要用到生成器?
    性能限制需要用到 , 比如读取一个10G的文件,如果一次性将10G的文件加载到内存处理的话(read方法),内存可能会溢出;但使用生成器把读写交叉处理进行 ,比如使用(readline和readlines)就可以再循环读取的同时不断处理,这样就可以节省大量的内存空间.

比如计算0到1000的数的平方:
使用生成式,会稍微等待一会才能看到结果,而且结果是全部计算完成才返回。
如果需要计算的数更大,那么等待时间会更长

nums = [i ** 2 for i in range(1001)]
print(nums) 

生成器的实现方式

将生成式改写成生成器。将[ ] 改成 ( )

使用生成器:
返回结果很快,而且返回的不是值,是一个generator。

nums = (i ** 2 for i in range(1001))
print(nums) 

在这里插入图片描述生成器能一边循环一边计算,在需要的时候再进行计算
如何打印出生成器的每一个元素呢

  • 通过for循环,依次计算并生成每一个元素
  • 如果要一个一个打印出来,可以通过 next( ) 函数获得生成器的下一个返回值
nums = (i ** 2 for i in range(1001))
print(next(nums))
print(next(nums))
print(next(nums))
print(next(nums))for num in nums:print(num)

在这里插入图片描述

使用yield关键字

先需要说明,return关键字:
函数遇到return就返回,return后面的代码不会执行

def login():a=1return "login"print(a)result=login()
print(result)

在这里插入图片描述

def login():print('step 1')yield 1print('step 2')yield 2print('step 3')yield 3result=login()
print(result)

当函数中有yield关键字,那么函数的返回值就是一个生成器
在这里插入图片描述由于生成器是边循环边计算,因此可以使用 next( )打印出生成器的结果。

函数遇到yield则会停止执行代码,当调用next方法时,会从上次停止的地方继续执行,遇到yield停止。。。

def login():print('step 1')yield 1    #返回1print('step 2')yield 2print('step 3')yield 3result=login()    #result是一个生成器
print(next(result)) #使用next()打印出生成器的第一个值
print(next(result))  #使用next()打印出生成器的第二个值

在这里插入图片描述
生成器的特点是什么?

  • 解耦. 爬虫与数据存储解耦;
  • 减少内存占用. 随时生产, 即时消费, 不用堆积在内存当中;
  • 可不终止调用. 写上循环, 即可循环接收数据, 对在循环之前定义的变量, 可重复使用;
  • 生成器的循环, 在 yield 处中断, 没那么占 cpu.

闭包

什么是时间戳:
从1970年1月1日到现在经历的秒数

# coding=gbk
import time
start_time=time.time() #时间戳
time.sleep(2)
end_time=time.time()
print(f'休眠时间:{end_time-start_time}秒')

在这里插入图片描述

闭包的特性:

  • 函数里面嵌套函数
  • 外部函数的返回值是内部函数的引用
  • 内部函数可以使用外部函数的变量
# coding=gbk
def timeit(name):def wrapper():print('wrapper '+name)print('timeit')return wrapper
in_fun=timeit('lee')  #in_fun实质上就是wrapper函数
in_fun()  #执行wrapper函数

在这里插入图片描述

装饰器

装饰器是用来装饰函数的工具

可以在不改变源代码的情况下,添加额外功能的工具。比如计算运行时间,记录日志,权限判断

如何实现装饰器?依靠闭包实现

下述程序,可以大致按照(1)(2)(3)(4)(5)(6)的顺序去执行

# coding=gbk
"""
需求:给计算两数之和的函数添加额外功能:计算该函数的运行时间
"""
# 定义装饰器
import timedef timeit(f): #(2)def wrapper(x, y):  #(4)start = time.time()  # 被装饰函数add执行之前,计算时间result = f(x, y)  # 2.f(x,y)实质上是add加法函数end = time.time()  # 被装饰函数add执行之后,计算时间print("函数运行时间为: %.4f" % (end - start))return resultreturn wrapper@timeit  # 1.语法糖  (1)
# add=timeit(add) 装饰器要装饰add函数,将add函数作为参数传入,并将返回值wrapper赋给被装饰的函数add
def add(x, y):   #(5)return x + yresult = add(1, 3) #此时执行add函数,其实执行的是wrapper函数  (3)
print(result)  #(6)

在这里插入图片描述
如何自己写一个装饰器?

#下述装饰器什么功能都没有,只是执行了被装饰函数
def timit(f): #f是被装饰的函数def wrapper(*args,**kwargs):result=f(*args,**kwargs) #执行被装饰函数return resultreturn  wrapper

定义一个login()函数,执行该函数能打印login…
现在希望给该函数添加功能,在打印login…之前,先显示一个欢迎界面
那么就可以借助装饰器,装饰器就能在不改变源代码的基础上,给函数附加功能。类似地,如果有别的函数也希望添加一个欢迎界面,也能直接使用该装饰器。

在wrapper函数内执行print(f._ _name_ _)能打印出被装饰函数的名称

def timit(f): #f是被装饰的函数def wrapper(*args,**kwargs):print("welcome...")result=f(*args,**kwargs) #执行被装饰函数print(f"被装饰函数{f.__name__}执行完毕") return resultreturn  wrapper@timit
def login():print("login...")login()

在这里插入图片描述

def timit(f): #f是被装饰的函数"""装饰器"""def wrapper(*args,**kwargs):"""wrapper内置函数"""print("welcome...")result=f(*args,**kwargs) #执行被装饰函数print(f"被装饰函数{f.__name__}执行完毕")return resultreturn  wrapper@timit
def login():"""login函数描述"""print("login...")print(help(login))

在这里插入图片描述
print(help(login))查看login的帮助文档,但是显示的是wrapper函数的帮助文档。
这是因为有装饰器,执行login函数的时候,其实执行的是wrapper。所以直接返回的是wrapper的帮助文档。怎么样才能实现访问login的说明文档就返回login的,不返回wrapper的?

from functools import wraps
def timit(f): #f是被装饰的函数"""装饰器"""@wraps(f) #保留被装饰函数的属性信息和帮助文档!!!def wrapper(*args,**kwargs):"""wrapper内置函数"""print("welcome...")result=f(*args,**kwargs) #执行被装饰函数print(f"被装饰函数{f.__name__}执行完毕")return resultreturn  wrapper@timit
def login():"""login函数描述"""print("login...")print(help(login))

通过 @wraps(f)装饰被装饰函数的属性信息,进而能保留被装饰函数的属性信息和帮助文档。
在这里插入图片描述
装饰器的实现模板:

#装饰器的万能模板:
def 装饰器名称(f):@wraps(f)  # 保留被装饰函数的属性信息和帮助文档def wrapper(*args, **kwargs):# 执行函数之前做的事情result = f(*args, **kwargs)# 执行函数之后做的事情return  resultreturn  wrapper

相关内容

热门资讯

demo什么意思 demo版本... 618快到了,各位的小金库大概也在准备开闸放水了吧。没有小金库的,也该向老婆撒娇卖萌服个软了,一切只...
应用未安装解决办法 平板应用未... ---IT小技术,每天Get一个小技能!一、前言描述苹果IPad2居然不能安装怎么办?与此IPad不...
脚上的穴位图 脚面经络图对应的... 人体穴位作用图解大全更清晰直观的标注了各个人体穴位的作用,包括头部穴位图、胸部穴位图、背部穴位图、胳...
世界上最漂亮的人 世界上最漂亮... 此前在某网上,选出了全球265万颜值姣好的女性。从这些数量庞大的女性群体中,人们投票选出了心目中最美...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
埃菲尔铁塔在哪 中国仿建埃菲尔... 2019年4月26日,广西南宁市,街头惊现一座巨型山寨版埃菲尔铁塔,高约20米,白色塔身,造型逼真,...
猫咪吃了塑料袋怎么办 猫咪误食... 你知道吗?塑料袋放久了会长猫哦!要说猫咪对塑料袋的喜爱程度完完全全可以媲美纸箱家里只要一有塑料袋的响...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
埃菲尔铁塔在哪 中国仿建埃菲尔... 2019年4月26日,广西南宁市,街头惊现一座巨型山寨版埃菲尔铁塔,高约20米,白色塔身,造型逼真,...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
长白山自助游攻略 吉林长白山游... 昨天介绍了西坡的景点详细请看链接:一个人的旅行,据说能看到长白山天池全凭运气,您的运气如何?今日介绍...
应用未安装解决办法 平板应用未... ---IT小技术,每天Get一个小技能!一、前言描述苹果IPad2居然不能安装怎么办?与此IPad不...
脚上的穴位图 脚面经络图对应的... 人体穴位作用图解大全更清晰直观的标注了各个人体穴位的作用,包括头部穴位图、胸部穴位图、背部穴位图、胳...