6、python的高级特性(生成式、生成器、闭包、装饰器)

news2024/11/25 2:51:22

文章目录

  • 生成式
    • 列表生成式
    • 字典生成式
    • 集合生成式
  • 生成器
    • 生成器的实现方式
      • 将生成式改写成生成器。将[ ] 改成 ( )
      • 使用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=1
    return "login"
    print(a)

result=login()
print(result)

在这里插入图片描述

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

result=login()
print(result)

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

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

def login():
    print('step 1')
    yield 1    #返回1
    print('step 2')
    yield 2
    print('step 3')
    yield 3

result=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 time

def 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 result
    return wrapper

@timeit  # 1.语法糖  (1)
# add=timeit(add) 装饰器要装饰add函数,将add函数作为参数传入,并将返回值wrapper赋给被装饰的函数add
def add(x, y):   #(5)
    return x + y

result = add(1, 3) #此时执行add函数,其实执行的是wrapper函数  (3)
print(result)  #(6)

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

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

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

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

相关文章

核心解读 - 2022版智慧城市数字孪生标准化白皮书

核心解读 - 2022版智慧城市数字孪生标准化白皮书前言:城市数字孪生基本概念一、城市数字孪生概述1、城市数字孪生内涵及概念模型2、城市数字孪生典型特征3、城市数字孪生相关方4、城市数字孪生技术参考架构5、城市数字孪生关键技术二、智慧城市数字孪生发展现状1、政…

JMeter下载及安装配置教程

参考:入门部署教程 – Jmeter中文网 本文是在win10环境下安装使用jmeter,jmeter可以运行在多平台上Windows和Linux。 环境准备: java 8 jmeter 5.1.1 jmeter环境 jmeter环境依赖JAVA环境,需安装JDK1.8环境,JDK下载地…

基于若依springboot二次开发WMS带移动端管理系统vue源码

系统是前后端分离的架构,前端使用Vue2,后端使用SpringBoot2。搭建部署的方式也是挺简单的,还带有uniapp开发的多端移动端扫码入库功能 技术架构 技术框架:SpringBoot2.0.0 Mybatis1.3.2 Shiro swagger-ui jpa lombok Vue2 …

轻薄笔记本能不能带起来高刷的显示器??

先说结论,新款集显也可以,用TYPC或者DP线连,使用时关闭主屏,只显示外屏。 这个问题,已经困扰了很久~~~ 软件上,windows以主屏作为主刷新率,除非笔记本自身是高刷屏,否则请只使用外…

单应性矩阵在标定中的应用

1.单应性矩阵是什么? 言简意赅定义:定义在两个不同视角中对同一平面范围内的特征点的射影变换(projective transformation)即: x1 H*x2 //x1、x2为匹配点 上图中x,x‘为一对匹配点,通过单应矩…

Pytest自动化框架运行全局配置文件pytest.ini

前言 还记得在之前的篇章中有讲到Pytest是目前主要流行的自动化框架之一,他有基础的脚本编码规则以及两种运行方式。 pytest的基础编码规则是可以进行修改,这就是今日文章重点。 看到这大家心中是否提出了两个问题:pytest的基础编码规则在…

Array_JavaScript

Array 学习路线:JavaScript基础语法(输出语句)->JavaScript基础语法(变量)->JavaScript基础语法(数据类型)->JavaScript基础语法(运算符)->JavaScript基础语…

python数据容器——列表

目录 一.数据容器 二.数据容器——列表 基本语法 注意 三.列表的下标(索引) 嵌套列表的下标(索引) 四.列表的常用操作(方法) 1.查询元素下标 2.插入元素 3.删除元素 4.统计元素 说明 一.数据容器 1&a…

使用react-sizeme解决react-grid-layout中侧栏(抽屉)展开或隐藏时不会自适应容器大小的问题

文章目录使用react-sizeme解决react-grid-layout中侧栏(抽屉)展开或隐藏时不会自适应容器大小的问题前提概要问题代码解决代码参考使用react-sizeme解决react-grid-layout中侧栏(抽屉)展开或隐藏时不会自适应容器大小的问题 前提概要 在上一篇博文中,我们讲到了使…

postgres源码解析38 表创建执行全流程梳理--2

本小节主要讲解查询执行模块,有机地调用存储、索引、事务、并发等模块,按照执行计划中的计划节点(操作执行接口)完成数据的读取或者修改。知识回顾:postgres源码解析37 表创建执行全流程梳理–1 关键数据结构 总图&a…

八、【React-Router5】路由组件传参

文章目录1、实现效果2、向路由组件传递参数总览3、修改上一节代码3.1、项目结构变更如下3.2、CODE(params传参)3.2.1、Messages.jsx3.2.2、Detail.jsx3.2.3、Result3.3、CODE(search传参)3.3.1、Messages.jsx3.3.2、Detail.jsx3.3…

【强化学习论文】小样本策略泛化的提示决策转换器

文献题目:Prompting Decision Transformer for Few-Shot Policy Generalization 摘要 人类可以利用先前的经验并从少量演示中学习新任务。与旨在通过更好的算法设计实现快速适应的离线元强化学习相比,我们研究了架构归纳偏差对少样本学习能力的影响。我…

RationalDMIS2022车削件(轴类)测量:回转体检测

1.坐标系知识 在三坐标测量机的使用中,坐标系的建立是最为关键的一步,是工件测量的基本依据。设备在组装本身中有着XYZ三个互相垂直的坐标轴,因此坐标系的建立便是通过以工件上的特征作为依据建立XYZ三个互相垂直的坐标轴与设备的坐标轴进行对应,从而使程序得以运行。 物…

虚拟机安装

虚拟机安装 能看到这里说明你的电脑中已经安装的有虚拟机了,如果没有虚拟机可以先下载安装一些虚拟机。 有了虚拟机后首先要准备的就是镜像,我用的是CentOS-7。如果没有的也可以百度或者去阿里云下载即可。 选择下载以ISO结尾的文件,可选类型…

SLAM学习笔记(二)

5.相机与图像 相机将三维世界中的坐标点(单位米)映射到二维图像平面(单位为像素)的过程中能够用一个几何模型进行描述。 单目相机(Mono)的成像过程: 1、世界坐标系下有个固定的点P,世界坐标为 2、由于相…

关于quartus 13.1出现的问题的一些总结

1,如果IP核的版本与当前的quartus ii版本不一致的情况,有时候虽然能编译成功,但是无法修改原有工程的IP核参数设置。 如: 之前我下载的工程用到的NCO IP核是12.1 version的,但是我用到的quartus 版本是13.0和13.1&am…

led灯什么牌子的质量好?2022双十二家用护眼台灯推荐

台灯作为一种晚上或者其他黑暗条件下的照明灯具,对于经常熬夜的人群来说可以说是必备工具了,无论是看书、写字,还是工作、学习,都非常实用,它不同于平常的家用的室内照明顶灯,光线不会那么刺眼,…

uni-app入门:小程序UI组件Vant Weapp

1.vant介绍 2.安装步骤 2.1 通过 npm 安装 2.2 修改 app.json 2.3 修改 project.config.json 2.4 构建 npm 包 3.使用说明 1.vant介绍Vant Weapp 是一个轻量、可靠的移动端组件库,于 2017 年开源,是由有赞前端团队开…

Mysql 安装与卸载

MySQL8.0.26-Linux版安装 文章目录MySQL8.0.26-Linux版安装1. 安装1.1 准备一台Linux服务器1.2. 下载Linux版MySQL安装包1.3. 上传MySQL安装包1.4. 创建目录,并解压1.5. 安装mysql的安装包1.6. 启动MySQL服务1.7. 查询自动生成的root用户密码1.8. 修改root用户密码1.9. 创建用户…

【FRP】群晖docker中部署Frp

2022-08-24 by 崔斐然 0:需求 公司有台笔记本,现在疫情期间居家办公。我用的MacBook RDP客户端做的非常好用,如相互粘贴文件、文字等,MacBook通过远程桌面连接公司内网电脑会比较方便,时延和体验感远优于向日葵。之前…