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

[复制链接]
发表于 2026-1-24 22:39:51 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
1、上下文管理器

(一)、with…open…
  1. with.open()格式:
  2.     with open(文件名, 模式, 码表) as 文件对象名:
  3.         正常的读写操作即可.
  4.     特点:
  5.         会在with.open()里边的代码执行完后后, 自动释放资源.
复制代码
现实上,with.open()它就是上下文管理器对象
  1. with open('./1.txt', 'r', encoding='utf-8') as src_f:
  2.     data = src_f.read()
  3.     print(f'读取到: {data}')
复制代码
(二)上下文管理器

概述
  1. 一个类只要实现了__enter__()和__exit__()方法,那么这个类就是一个上下文管理器类.
  2. 该类的对象 = 上下文管理器对象.
复制代码
特点

  • 上下文管理器对象, 可以联合with语句使用.
  • 在with语句实行前, 会主动调用__ enter __()方法, 用于初始化某些 变量.
  • 在with语句实行后, 会主动调用__ exit __()方法, 用于整理某些资源, 纵然前边有Bug也会调用该方法.
比方–返回类的属性(文件对象)
  1. # 1. 定义1个上下文管理器类, 表示: 我们自己的处理文件的操作.
  2. class MyFile:
  3.     # 2. 在 init魔法方法中, 初始化: 属性信息.
  4.     def __init__(self, file_name, mode):
  5.         # 文件名(文件路径)
  6.         self.file_name = file_name
  7.         # 模式, r, w...
  8.         self.mode = mode
  9.         # 文件对象
  10.         self.file_obj = None
  11.     # 3. 在enter魔法方法中, 获取1个: 文件对象, 用于读写文件操作.
  12.     def __enter__(self):
  13.         print('我是 enter 魔法方法')
  14.         # 获取文件对象
  15.         self.file_obj = open(self.file_name, self.mode, encoding='utf-8')
  16.         # 返回文件对象.
  17.         return self.file_obj    # file_obj = open()对象
  18.     # 4. 在exit魔法方法中, 关闭文件对象.
  19.     def __exit__(self, exc_type, exc_val, exc_tb):
  20.         self.file_obj.close()
  21.         print('文件对象已被关闭...')
  22. # 5. 在main方法中, 测试自定义的 文件对象.
  23. if __name__ == '__main__':
  24.     # 如果 enter魔法方法返回的是: open()对象, 代码如下
  25.     with MyFile('./1.txt', 'r') as file_obj:
  26.         # print( 10 / 0)    # 即使有Bug, 也会尝试关闭资源.
  27.         data = file_obj.read()
  28.         print(f'读取到: {data}')
复制代码
比方–返回类对象
  1. # 1. 定义1个上下文管理器类, 表示: 我们自己的处理文件的操作.
  2. class MyFile:
  3.     # 2. 在 init魔法方法中, 初始化: 属性信息.
  4.     def __init__(self, file_name, mode):
  5.         # 文件名(文件路径)
  6.         self.file_name = file_name
  7.         # 模式, r, w...
  8.         self.mode = mode
  9.         # 文件对象
  10.         self.file_obj = None
  11.     # 3. 在enter魔法方法中, 获取1个: 文件对象, 用于读写文件操作.
  12.     def __enter__(self):
  13.         print('我是 enter 魔法方法')
  14.         # 获取文件对象
  15.         self.file_obj = open(self.file_name, self.mode, encoding='utf-8')
  16.         # 返回文件对象.
  17.         return self           # self = MyFile的对象
  18.     # 4. 在exit魔法方法中, 关闭文件对象.
  19.     def __exit__(self, exc_type, exc_val, exc_tb):
  20.         self.file_obj.close()
  21.         print('文件对象已被关闭...')
  22. # 5. 在main方法中, 测试自定义的 文件对象.
  23. if __name__ == '__main__':
  24.     # 如果 enter魔法方法返回的是: MyFile对象, 代码如下.
  25.     with MyFile('./1.txt', 'r') as mf:
  26.         # print( 10 / 0)    # 即使有Bug, 也会尝试关闭资源.
  27.         data = mf.file_obj.read()
  28.         print(f'读取到: {data}')
复制代码
(三)、总结

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

(一)、简介

概述
天生器指的是 Generator对象, 它不再是像以往一样, 一次性天生全部的数据. 而是用一个, 再生产一个.
基于用户写的规则(条件)来天生数据, 假如条件不建立, 则天生竣事.
目的
节省内存资源, 镌汰内存占用.
实现方法

  • 推导式写法
  • yield关键字实现
迭代
迭代指的是: 逐个的从容器范例中获取每一个元素的过程, 称之为: 迭代(遍历)
比方: 列表, 聚集, 字典, 天生器等, 都是可以遍历(迭代)的, 以是它们也称之为: 可迭代对象
从天生器中获取数据

  • next()函数
  • 遍历
(二)、推导式写法
  1. # 案例: 演示推导式写法, 获取生成器对象.
  2. if __name__ == '__main__':
  3.     # 1. 回顾: 列表推导式.
  4.     list1 = [i for i in range(1, 6)]
  5.     print(f'list1: {list1}')             # [1, 2, 3, 4, 5]
  6.     print(f'list1的类型: {type(list1)}')  # <class 'list'>
  7.     # 2. 回顾: 字典推导式.
  8.     dict1 = {i: i ** 2 for i in range(1, 6)}
  9.     print(f'dict1: {dict1}')
  10.     print(f'dict1的类型: {type(dict1)}')  # <class 'dict'>
  11.     # 3. 回顾: 集合推导式.
  12.     set1 = {i for i in range(1, 6)}
  13.     print(f'set1: {set1}')
  14.     print(f'set1的类型: {type(set1)}')    # <class 'set'>
  15.     print('-' * 21)
  16.     # 4. 尝试写1个"元组推导式", 注意: 没有元组推导式这个说法, 它的底层是: 生成器对象.
  17.     # 生成器写法1: 推导式写法.
  18.     my_generator = (i for i in range(1, 6))
  19.     print(f'my_generator: {my_generator}')            # 地址值
  20.     print(f'my_generator的类型: {type(my_generator)}') # <class 'generator'>
  21.     print('-' * 21)
  22.     # 5. 生成器不是一下子生成所有的数据, 而是用一个再生成1个.
  23.     # 问: 如何从生成器中获取数据呢?
  24.     # 答: 1: next()函数.   2.for循环遍历.
  25.     # 方式1: next()函数, 从生成器中获取数据.
  26.     print(next(my_generator))
  27.     print(next(my_generator))
  28.     print(next(my_generator))
  29.     print(next(my_generator))
  30.     print(next(my_generator))
  31.     # print(next(my_generator))   # 报错: StopIteration, 停止迭代
  32.     print('-' * 21)
  33.     # 方式2: for循环遍历, 获取生成器的数据
  34.     # 细节: next()是移动指针的, 获取下个元素, 如果不注释上边的代码, 这里打印结果是 空.
  35.     for i in my_generator:
  36.         print(i)
复制代码
(三)、yield写法
  1. # 需求: 获取 1 ~ 10之间的整数, 生成器写法.
  2. # 1. 定义函数, 获取: 生成器对象.
  3. def get_generator():
  4.     # 回顾: list写法
  5.     # list_data = []
  6.     # for i in range(1, 11):
  7.     #     list_data.append(i)
  8.     # return list_data      # 返回列表对象
  9.     # 对比: yield写法, 效果类似于上边的代码, 只不过返回的是: 生成器对象.
  10.     for i in range(1, 11):
  11.         yield i   # yield的作用: 1.创建生成器对象.  2.逐个的把每个元素放到生成器对象中.  3.函数结束时, 返回生成器对象.
  12. # 2. 测试上述的函数.
  13. if __name__ == '__main__':
  14.     # 3. 调用函数, 获取生成器对象.
  15.     my_generator = get_generator()
  16.     print(type(my_generator))       # <class 'generator'>
  17.     # 4. 从生成器对象中, 获取数据.
  18.     # 方式1: next()函数
  19.     print(next(my_generator))   # 1
  20.     print(next(my_generator))   # 2
  21.     print(next(my_generator))   # 3
  22.     print('-' * 21)
  23.     # 方式2: 遍历.
  24.     for i in my_generator:
  25.         print(i)
复制代码
需求
  1. import math
  2. # 案例1: 定义函数 dataset_loader(batch_size), 用于获取: 批次数据.
  3. def dataset_loader(batch_size):
  4.     """
  5.     自定义的函数, 获取批次数据的.
  6.     :param batch_size: 每批次数据的条数.
  7.     :return: 生成器对象, 每个数据 = 1批的数据
  8.     """
  9.     # 1. 读取源文件, 获取到所有的数据.
  10.     with open('./data/jaychou_lyrics.txt', 'r', encoding='utf-8') as src_f:
  11.         # 一次性读取所有的行, 并放到列表中.
  12.         list_data = src_f.readlines()  # 数据格式: ['第1行\n', '第2行\n', '第3行\n'...]
  13.     # 2. 获取数据的总条数.
  14.     line_count = len(list_data)
  15.     # 3. 根据数据的总条数, 结合每批次的数据条数, 计算: 总批次数.
  16.     batch_count = math.ceil(line_count / batch_size)
  17.     # 4. 遍历 总批次数, 获取到: 每个批次的 编号, 然后生成: 该批次的数据.
  18.     for batch_idx in range(batch_count):
  19.         """
  20.         推理过程:
  21.             假设 batch_size = 8, batch_count = 13, 即: 13批, 8条/批, 则:
  22.             batch_idx = 0, 代表第1批数据, 数据为: 第1条 ~ 第8条, 索引为: [0:8]
  23.             batch_idx = 1, 代表第2批数据, 数据为: 第9条 ~ 第16条, 索引为: [8:16]
  24.             batch_idx = 2, 代表第3批数据, 数据为: 第17条 ~ 第24条, 索引为: [16:24]
  25.             ......
  26.         """
  27.         yield list_data[batch_idx * batch_size: batch_idx * batch_size + batch_size]
  28. # 在main函数中测试.
  29. if __name__ == '__main__':
  30.     # 5. 获取生成器对象.
  31.     data_loader = dataset_loader(batch_size=8)
  32.     # 6. 获取第1批次的数据.
  33.     # print(next(data_loader))
  34.     batch_data1 = next(data_loader)
  35.     # 具体的获取第1批次中每条数据的过程.
  36.     for line in batch_data1:
  37.         print(line, end='')
  38.     print('-' * 21)
  39.     # 7. 获取第2批次的数据.
  40.     print(next(data_loader))
复制代码
3、property

(一)、简介

概述
用来装饰函数,装饰后,可以把函数当做变量来用.
目的
简化开辟,进步服从
用法

  • 充当装饰器用
  • 修饰类变量
(二)、用做装饰器

用法
  1. 1. 在 获取值的函数上, 加上 @property
  2. 2. 在 设置值的函数上, 加上 @方法名.setter, 注意: 这里的方法名是 @property修饰的方法名
  3. 3. 之后就可以把 函数 当做 变量来直接使用了.
复制代码
比方
  1. # 需求: 定义学生类, 有个私有的属性name, 提供公共的访问方式, 并测试.
  2. # 1. 定义学生类.
  3. class Student:
  4.     # 2. 私有属性.
  5.     def __init__(self):
  6.         self.__name = '张三'      # 私有属性.
  7.     # 3. 获取值的方法.
  8.     # @property
  9.     # def get_name(self):
  10.     #     return self.__name
  11.     #
  12.     # # 4. 设置值的方法.
  13.     # @get_name.setter
  14.     # def set_name(self, name):
  15.     #     self.__name = name
  16.     # 5. get_xxx(), set_xxx()函数 如果结合 property装饰器用, 具体写法如下:
  17.     # 获取值的方法
  18.     @property
  19.     def name(self):
  20.         return self.__name
  21.     # 设置值的方法.
  22.     @name.setter
  23.     def name(self, name):
  24.         # 根据需求, 可以对传入的值做校验.
  25.         # if name == '段誉':
  26.         #     print('名字不能为段誉')
  27.         # else:
  28.         #     self.__name = name
  29.         # 直接赋值.
  30.         self.__name = name
  31. # 在main中测试.
  32. if __name__ == '__main__':
  33.     # 6. 创建学生对象.
  34.     s = Student()
  35.     # 7. 访问Student类的私有属性name
  36.     # print(s.name)       # 报错
  37.     # print(s.__name)     # 报错.
  38.     # s.set_name('乔峰')
  39.     # print(s.get_name())
  40.     # 8. 访问Student类的私有属性name
  41.     # s.set_name = '虚竹'
  42.     # print(s.get_name)
  43.     # 看起来调用的是"属性", 其实底层是: 函数.
  44.     s.name = '段誉'
  45.     print(s.name)
复制代码
(三)、类属性

用法
  1. 1. 直接在类中编写 类变量名 = property(获取值的方法名, 设置值的方法名)
  2. 2. 之后就可以通过 类名.类变量名的方式 来使用了, 这个是充当: 类变量的.
  3. 3. 如果要精准的修改或者获取某个学生的信息, 可以通过 对象名.属性名的方式调用.
复制代码
比方
  1. # 需求: 定义学生类, 有个私有的属性name, 提供公共的访问方式, 并测试.
  2. # 1. 定义学生类.
  3. class Student:
  4.     # 2. 私有属性.
  5.     def __init__(self):
  6.         self.__name = '张三'      # 私有属性.
  7.     # 3. 获取值的方法.
  8.     def get_name(self):
  9.         return self.__name
  10.     # 4. 设置值的方法.
  11.     def set_name(self, name):
  12.         self.__name = name
  13.     # 5. property充当类属性的用法.
  14.     # 参1: 获取值的函数.
  15.     # 参2: 设置值的函数.
  16.     # 注意: 顺序不要写反了, 这个是固定的顺序, 写反了会报错.
  17.     name = property(get_name, set_name)
  18. # 在main中测试.
  19. if __name__ == '__main__':
  20.     # 6. 创建学生对象.
  21.     s = Student()
  22.     s.name = '乔峰'         # 对象属性
  23.     # Student.name = '乔峰' # 类属性
  24.     print(s.name)
  25.     print('-' * 21)
  26.     # 7. 再次创建学生对象.
  27.     s2 = Student()
  28.     print(s2.name)
复制代码
4、迭代器

(一)、简介

概述
类中只要实现了__ next __ ()和 __ iter __ (),它就是迭代器类。
作用
逐个遍历,获取元素值,目的是镌汰内存的占用。
用一个拿一个,一样寻常联合天生器对象使用。
(二)、实现
  1. class MyIterator():
  2.     # 给一个默认的限制值
  3.     def __init__(self, limit):
  4.         self.limit = limit
  5.         self.current = 0
  6.    
  7.     # 重写__next__()函数
  8.     def __next__(self):
  9.         if self.current >= self.limit:
  10.             # 抛出异常,终止程序
  11.             raise StopIteration
  12.         # 计数
  13.         self.current += 1
  14.         # 返回当前计数
  15.         return self.current
  16.     def __iter__(self):
  17.         # 返回对象本身
  18.         return self
  19. if __name__ == '__main__':
  20.     my_iter = MyIterator(5)
  21.     print(type(my_iter)) # <class '__main__.MyIterator'>
  22.     for i in my_iter:
  23.         print(i)
  24.     # 如果再读取就会触发上面的异常
  25.     # print(next(my_iter))
复制代码
5、json字符串处理处罚

(一)、简介

概述
JS的对象表现法,轻量级的数据交互格式。
作用
比力得当人们的阅读和编写,也比力得当盘算机的辨认和编译。
格式
  1. '{"键名": "值", "键名": "值"}'
复制代码
使用步调
  1. # 导包
  2. import json
  3. # 解析
  4. # Json字符串 => Json对象
  5. loads()
  6. # 格式化
  7. # Json对象 => Json字符串
  8. dumps()
复制代码
(二)、实现

剖析
  1. # 解析
  2. json_str = '{"name": "乔峰", "age": 39, "kongfu": "降龙十八掌"}'
  3. print(type(json_str))  # <class 'str'>
  4. # 方式一
  5. # json_obj = json.loads(json_str)
  6. # print(type(json_obj))  # <class 'dict'>
  7. # print(json_obj)        # {'name': '乔峰', 'age': 39, 'kongfu': '降龙十八掌'}
  8. # 方式二
  9. json_obj = eval(json_str)
  10. print(type(json_obj))    # <class 'dict'>
复制代码
格式化
  1. # 格式化
  2. # dumps默认用ascii码表解析,默认是True
  3. # json_str = json.dumps(json_obj)  # {"name": "\u4e54\u5cf0", "age": 39, "kongfu": "\u964d\u9f99\u5341\u516b\u638c"}
  4. json_str = json.dumps(json_obj, ensure_ascii=False)  #{"name": "乔峰", "age": 39, "kongfu": "降龙十八掌"}
  5. print(json_str)
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!qidao123.com:ToB企服之家,中国第一个企服评测及软件市场,开放入驻,技术点评得现金
回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表