当前位置: 首页 > news >正文

一些实用的高阶用法--python

1、上下文管理器

(一)、with…open…

with.open()格式:with open(文件名, 模式, 码表) as 文件对象名:正常的读写操作即可.特点:会在with.open()里边的代码执行完后后, 自动释放资源.

实际上,with.open()它就是上下文管理器对象

with open('./1.txt', 'r', encoding='utf-8') as src_f:data = src_f.read()print(f'读取到: {data}')

(二)上下文管理器

概述

一个类只要实现了__enter__()和__exit__()方法,那么这个类就是一个上下文管理器类.
该类的对象 = 上下文管理器对象.

特点

  • 上下文管理器对象, 可以结合with语句使用.
  • 在with语句执行前, 会自动调用__ enter __()方法, 用于初始化某些 变量.
  • 在with语句执行后, 会自动调用__ exit __()方法, 用于清理某些资源, 即使前边有Bug也会调用该方法.

例如–返回类的属性(文件对象)

# 1. 定义1个上下文管理器类, 表示: 我们自己的处理文件的操作.
class MyFile:# 2. 在 init魔法方法中, 初始化: 属性信息.def __init__(self, file_name, mode):# 文件名(文件路径)self.file_name = file_name# 模式, r, w...self.mode = mode# 文件对象self.file_obj = None# 3. 在enter魔法方法中, 获取1个: 文件对象, 用于读写文件操作.def __enter__(self):print('我是 enter 魔法方法')# 获取文件对象self.file_obj = open(self.file_name, self.mode, encoding='utf-8')# 返回文件对象.return self.file_obj    # file_obj = open()对象# 4. 在exit魔法方法中, 关闭文件对象.def __exit__(self, exc_type, exc_val, exc_tb):self.file_obj.close()print('文件对象已被关闭...')# 5. 在main方法中, 测试自定义的 文件对象.
if __name__ == '__main__':# 如果 enter魔法方法返回的是: open()对象, 代码如下with MyFile('./1.txt', 'r') as file_obj:# print( 10 / 0)    # 即使有Bug, 也会尝试关闭资源.data = file_obj.read()print(f'读取到: {data}')

例如–返回类对象

# 1. 定义1个上下文管理器类, 表示: 我们自己的处理文件的操作.
class MyFile:# 2. 在 init魔法方法中, 初始化: 属性信息.def __init__(self, file_name, mode):# 文件名(文件路径)self.file_name = file_name# 模式, r, w...self.mode = mode# 文件对象self.file_obj = None# 3. 在enter魔法方法中, 获取1个: 文件对象, 用于读写文件操作.def __enter__(self):print('我是 enter 魔法方法')# 获取文件对象self.file_obj = open(self.file_name, self.mode, encoding='utf-8')# 返回文件对象.return self           # self = MyFile的对象# 4. 在exit魔法方法中, 关闭文件对象.def __exit__(self, exc_type, exc_val, exc_tb):self.file_obj.close()print('文件对象已被关闭...')# 5. 在main方法中, 测试自定义的 文件对象.
if __name__ == '__main__':# 如果 enter魔法方法返回的是: MyFile对象, 代码如下.with MyFile('./1.txt', 'r') as mf:# print( 10 / 0)    # 即使有Bug, 也会尝试关闭资源.data = mf.file_obj.read()print(f'读取到: {data}')

(三)、总结

在__ enter __这个魔法方法,可以选择返回类对象,也可以选择返回类属性,这个只影响后续读取文件的写法格式。

2、生成器

(一)、简介

概述

生成器指的是 Generator对象, 它不再是像以往一样, 一次性生成所有的数据. 而是用一个, 再生产一个.
基于用户写的规则(条件)来生成数据, 如果条件不成立, 则生成结束.

目的

节约内存资源, 减少内存占用.

实现方法

  • 推导式写法
  • yield关键字实现

迭代

迭代指的是: 逐个的从容器类型中获取每一个元素的过程, 称之为: 迭代(遍历)
例如: 列表, 集合, 字典, 生成器等, 都是可以遍历(迭代)的, 所以它们也称之为: 可迭代对象

从生成器中获取数据

  • next()函数
  • 遍历

(二)、推导式写法

# 案例: 演示推导式写法, 获取生成器对象.
if __name__ == '__main__':# 1. 回顾: 列表推导式.list1 = [i for i in range(1, 6)]print(f'list1: {list1}')             # [1, 2, 3, 4, 5]print(f'list1的类型: {type(list1)}')  # <class 'list'># 2. 回顾: 字典推导式.dict1 = {i: i ** 2 for i in range(1, 6)}print(f'dict1: {dict1}')print(f'dict1的类型: {type(dict1)}')  # <class 'dict'># 3. 回顾: 集合推导式.set1 = {i for i in range(1, 6)}print(f'set1: {set1}')print(f'set1的类型: {type(set1)}')    # <class 'set'>print('-' * 21)# 4. 尝试写1个"元组推导式", 注意: 没有元组推导式这个说法, 它的底层是: 生成器对象.# 生成器写法1: 推导式写法.my_generator = (i for i in range(1, 6))print(f'my_generator: {my_generator}')            # 地址值print(f'my_generator的类型: {type(my_generator)}') # <class 'generator'>print('-' * 21)# 5. 生成器不是一下子生成所有的数据, 而是用一个再生成1个.# 问: 如何从生成器中获取数据呢?# 答: 1: next()函数.   2.for循环遍历.# 方式1: next()函数, 从生成器中获取数据.print(next(my_generator))print(next(my_generator))print(next(my_generator))print(next(my_generator))print(next(my_generator))# print(next(my_generator))   # 报错: StopIteration, 停止迭代print('-' * 21)# 方式2: for循环遍历, 获取生成器的数据# 细节: next()是移动指针的, 获取下个元素, 如果不注释上边的代码, 这里打印结果是 空.for i in my_generator:print(i)

(三)、yield写法

# 需求: 获取 1 ~ 10之间的整数, 生成器写法.
# 1. 定义函数, 获取: 生成器对象.
def get_generator():# 回顾: list写法# list_data = []# for i in range(1, 11):#     list_data.append(i)# return list_data      # 返回列表对象# 对比: yield写法, 效果类似于上边的代码, 只不过返回的是: 生成器对象.for i in range(1, 11):yield i   # yield的作用: 1.创建生成器对象.  2.逐个的把每个元素放到生成器对象中.  3.函数结束时, 返回生成器对象.# 2. 测试上述的函数.
if __name__ == '__main__':# 3. 调用函数, 获取生成器对象.my_generator = get_generator()print(type(my_generator))       # <class 'generator'># 4. 从生成器对象中, 获取数据.# 方式1: next()函数print(next(my_generator))   # 1print(next(my_generator))   # 2print(next(my_generator))   # 3print('-' * 21)# 方式2: 遍历.for i in my_generator:print(i)

需求

import math
# 案例1: 定义函数 dataset_loader(batch_size), 用于获取: 批次数据.
def dataset_loader(batch_size):"""自定义的函数, 获取批次数据的.:param batch_size: 每批次数据的条数.:return: 生成器对象, 每个数据 = 1批的数据"""# 1. 读取源文件, 获取到所有的数据.with open('./data/jaychou_lyrics.txt', 'r', encoding='utf-8') as src_f:# 一次性读取所有的行, 并放到列表中.list_data = src_f.readlines()  # 数据格式: ['第1行\n', '第2行\n', '第3行\n'...]# 2. 获取数据的总条数.line_count = len(list_data)# 3. 根据数据的总条数, 结合每批次的数据条数, 计算: 总批次数.batch_count = math.ceil(line_count / batch_size)# 4. 遍历 总批次数, 获取到: 每个批次的 编号, 然后生成: 该批次的数据.for batch_idx in range(batch_count):"""推理过程:假设 batch_size = 8, batch_count = 13, 即: 13批, 8条/批, 则:batch_idx = 0, 代表第1批数据, 数据为: 第1条 ~ 第8条, 索引为: [0:8]batch_idx = 1, 代表第2批数据, 数据为: 第9条 ~ 第16条, 索引为: [8:16]batch_idx = 2, 代表第3批数据, 数据为: 第17条 ~ 第24条, 索引为: [16:24]......"""yield list_data[batch_idx * batch_size: batch_idx * batch_size + batch_size]# 在main函数中测试.
if __name__ == '__main__':# 5. 获取生成器对象.data_loader = dataset_loader(batch_size=8)# 6. 获取第1批次的数据.# print(next(data_loader))batch_data1 = next(data_loader)# 具体的获取第1批次中每条数据的过程.for line in batch_data1:print(line, end='')print('-' * 21)# 7. 获取第2批次的数据.print(next(data_loader))

3、property

(一)、简介

概述

用来装饰函数,装饰后,可以把函数当做变量来用.

目的

简化开发,提高效率

用法

  • 充当装饰器用
  • 修饰类变量

(二)、用做装饰器

用法

1. 在 获取值的函数上, 加上 @property
2. 在 设置值的函数上, 加上 @方法名.setter, 注意: 这里的方法名是 @property修饰的方法名
3. 之后就可以把 函数 当做 变量来直接使用了.

例如

# 需求: 定义学生类, 有个私有的属性name, 提供公共的访问方式, 并测试.
# 1. 定义学生类.
class Student:# 2. 私有属性.def __init__(self):self.__name = '张三'      # 私有属性.# 3. 获取值的方法.# @property# def get_name(self):#     return self.__name## # 4. 设置值的方法.# @get_name.setter# def set_name(self, name):#     self.__name = name# 5. get_xxx(), set_xxx()函数 如果结合 property装饰器用, 具体写法如下:# 获取值的方法@propertydef name(self):return self.__name# 设置值的方法.@name.setterdef name(self, name):# 根据需求, 可以对传入的值做校验.# if name == '段誉':#     print('名字不能为段誉')# else:#     self.__name = name# 直接赋值.self.__name = name# 在main中测试.
if __name__ == '__main__':# 6. 创建学生对象.s = Student()# 7. 访问Student类的私有属性name# print(s.name)       # 报错# print(s.__name)     # 报错.# s.set_name('乔峰')# print(s.get_name())# 8. 访问Student类的私有属性name# s.set_name = '虚竹'# print(s.get_name)# 看起来调用的是"属性", 其实底层是: 函数.s.name = '段誉'print(s.name)

(三)、类属性

用法

1. 直接在类中编写 类变量名 = property(获取值的方法名, 设置值的方法名)
2. 之后就可以通过 类名.类变量名的方式 来使用了, 这个是充当: 类变量的.
3. 如果要精准的修改或者获取某个学生的信息, 可以通过 对象名.属性名的方式调用.

例如

# 需求: 定义学生类, 有个私有的属性name, 提供公共的访问方式, 并测试.
# 1. 定义学生类.
class Student:# 2. 私有属性.def __init__(self):self.__name = '张三'      # 私有属性.# 3. 获取值的方法.def get_name(self):return self.__name# 4. 设置值的方法.def set_name(self, name):self.__name = name# 5. property充当类属性的用法.# 参1: 获取值的函数.# 参2: 设置值的函数.# 注意: 顺序不要写反了, 这个是固定的顺序, 写反了会报错.name = property(get_name, set_name)# 在main中测试.
if __name__ == '__main__':# 6. 创建学生对象.s = Student()s.name = '乔峰'         # 对象属性# Student.name = '乔峰' # 类属性print(s.name)print('-' * 21)# 7. 再次创建学生对象.s2 = Student()print(s2.name)

4、迭代器

(一)、简介

概述

类中只要实现了__ next __ ()和 __ iter __ (),它就是迭代器类。

作用

逐个遍历,获取元素值,目的是减少内存的占用。

用一个拿一个,一般结合生成器对象使用。

(二)、实现

class MyIterator():# 给一个默认的限制值def __init__(self, limit):self.limit = limitself.current = 0# 重写__next__()函数def __next__(self):if self.current >= self.limit:# 抛出异常,终止程序raise StopIteration# 计数self.current += 1# 返回当前计数return self.currentdef __iter__(self):# 返回对象本身return selfif __name__ == '__main__':my_iter = MyIterator(5)print(type(my_iter)) # <class '__main__.MyIterator'>for i in my_iter:print(i)# 如果再读取就会触发上面的异常# print(next(my_iter))

5、json字符串处理

(一)、简介

概述

JS的对象表示法,轻量级的数据交互格式。

作用

比较适合人们的阅读和编写,也比较适合计算机的识别和编译。

格式

'{"键名": "值", "键名": "值"}'

使用步骤

# 导包
import json
# 解析
# Json字符串 => Json对象
loads()
# 格式化
# Json对象 => Json字符串
dumps()

(二)、实现

解析

# 解析
json_str = '{"name": "乔峰", "age": 39, "kongfu": "降龙十八掌"}'
print(type(json_str))  # <class 'str'># 方式一
# json_obj = json.loads(json_str)
# print(type(json_obj))  # <class 'dict'>
# print(json_obj)        # {'name': '乔峰', 'age': 39, 'kongfu': '降龙十八掌'}# 方式二
json_obj = eval(json_str)
print(type(json_obj))    # <class 'dict'>

格式化

# 格式化
# dumps默认用ascii码表解析,默认是True
# json_str = json.dumps(json_obj)  # {"name": "\u4e54\u5cf0", "age": 39, "kongfu": "\u964d\u9f99\u5341\u516b\u638c"}
json_str = json.dumps(json_obj, ensure_ascii=False)  #{"name": "乔峰", "age": 39, "kongfu": "降龙十八掌"}
print(json_str)

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • OpenCV结构分析与形状描述符(17)判断轮廓是否为凸多边形的函数isContourConvex()的使用
  • 监控易监测对象及指标之:全面监控Oracle数据库
  • cartographer从入门到精通(一):cartographer介绍
  • java八股!5(线程创建+并发容器+线程锁)
  • [网络原理]关于网络的基本概念 及 协议
  • 郑州建筑智能化乙级资质申请,人员资质要求详解
  • NLP-文本分类文献阅读-前置基础-词汇解释-通俗易懂-9月份-学习总结
  • 如何将 Electron 项目上架 Apple Store
  • JDBC API详解二
  • 基于SSM和VUE的药品管理系统(含源码+sql+视频导入教程+文档)
  • 解锁全球机遇:澳大利亚服务器租用市场的独特魅力
  • 音视频入门基础:WAV专题(9)——FFmpeg源码中计算WAV音频文件每个packet的duration和duration_time的实现
  • 网络原理(3)—— 应用层、传输层(TCP)
  • Redis 是否存在线程安全问题:深入解析与技术分析
  • Robust Image Denoising through Adversarial Frequency Mixup
  • [PHP内核探索]PHP中的哈希表
  • [iOS]Core Data浅析一 -- 启用Core Data
  • 8年软件测试工程师感悟——写给还在迷茫中的朋友
  • Apache的基本使用
  • Asm.js的简单介绍
  • Mocha测试初探
  • Rancher-k8s加速安装文档
  • Stream流与Lambda表达式(三) 静态工厂类Collectors
  • 对象引论
  • 飞驰在Mesos的涡轮引擎上
  • 今年的LC3大会没了?
  • 如何使用 OAuth 2.0 将 LinkedIn 集成入 iOS 应用
  • 使用SAX解析XML
  • 问题之ssh中Host key verification failed的解决
  • 小程序 setData 学问多
  • 用简单代码看卷积组块发展
  • 自定义函数
  • 你对linux中grep命令知道多少?
  • ​软考-高级-信息系统项目管理师教程 第四版【第14章-项目沟通管理-思维导图】​
  • ​字​节​一​面​
  • "无招胜有招"nbsp;史上最全的互…
  • # Swust 12th acm 邀请赛# [ K ] 三角形判定 [题解]
  • # 透过事物看本质的能力怎么培养?
  • #QT(TCP网络编程-服务端)
  • (4) openssl rsa/pkey(查看私钥、从私钥中提取公钥、查看公钥)
  • (保姆级教程)Mysql中索引、触发器、存储过程、存储函数的概念、作用,以及如何使用索引、存储过程,代码操作演示
  • (二) 初入MySQL 【数据库管理】
  • (附源码)springboot 房产中介系统 毕业设计 312341
  • (附源码)springboot学生选课系统 毕业设计 612555
  • (论文阅读32/100)Flowing convnets for human pose estimation in videos
  • (四)opengl函数加载和错误处理
  • (一)基于IDEA的JAVA基础10
  • (转)程序员技术练级攻略
  • (转)关于pipe()的详细解析
  • (转)原始图像数据和PDF中的图像数据
  • ***详解账号泄露:全球约1亿用户已泄露
  • ... 是什么 ?... 有什么用处?
  • .Net Redis的秒杀Dome和异步执行
  • .NET 药厂业务系统 CPU爆高分析
  • .Net6 Api Swagger配置