Python开发之迭代器&生成器的实战案例分享
作者:不背锅运维 发布时间:2021-03-18 17:34:33
迭代器&生成器
在 Python 中,迭代器和生成器都是用来遍历数据集合的工具,可以按需逐个生成或返回数据,从而避免一次性加载整个数据集合所带来的性能问题和内存消耗问题。
具体来说,迭代器是一个包含 iter() 和 next() 方法的对象,它通过 next() 方法依次返回数据集合中的每个元素,直到没有元素时引发 StopIteration 异常。迭代器可以自定义,也可以使用 Python 内置的可迭代对象,如列表、元组、字典、集合等,以及内置的迭代器函数,如 zip()、map()、filter() 等。
而生成器是一种特殊的迭代器,它使用 yield 关键字来定义,可以在需要时生成数据,从而实现按需生成、惰性计算的效果。生成器可以大大简化代码,提高性能和可读性,也可以通过生成器表达式快速创建简单的生成器。
下面分享几个贴近实际运维开发工作中的场景案例。
实战案例
1.假设需要从一个非常大的数据集合中查找满足特定条件的元素,并且只需要找到第一个符合条件的元素即可停止查找。如果直接遍历整个数据集合,可能会导致性能问题。这时可以使用迭代器和生成器来解决这个问题。
def find_first_match(data, condition):
for item in data:
if condition(item):
return item
raise ValueError('No matching item found')
large_data = [i for i in range(10000000)] # 构造一个大数据集合
match = find_first_match(large_data, lambda x: x > 1000) # 查找第一个大于 1000 的元素
print(match)
2.假设要实现一个函数,它接受一个字符串列表,然后返回这些字符串中所有字符的出现次数。可以使用迭代器和生成器来避免遍历整个列表,并减少内存使用量。
def char_count(words):
counts = {}
for word in words:
for char in word:
counts[char] = counts.get(char, 0) + 1
return counts
def char_count_lazy(words):
def char_gen(words):
for word in words:
for char in word:
yield char
counts = {}
for char in char_gen(words):
counts[char] = counts.get(char, 0) + 1
return counts
3.需要遍历一个多级嵌套的 JSON 对象,查找其中某个特定的值。假设 JSON 对象很大,因此不能一次性加载到内存中。这时可以使用生成器来逐级遍历 JSON 对象。
def find_value(json_obj, target_key):
if isinstance(json_obj, dict):
for key, value in json_obj.items():
if key == target_key:
yield value
else:
yield from find_value(value, target_key)
elif isinstance(json_obj, list):
for item in json_obj:
yield from find_value(item, target_key)
json_data = {
"name": "tantianran",
"age": 30,
"cars": [
{"model": "BMW", "year": 2000},
{"model": "Tesla", "year": 2020}
],
"location": {
"address": "123 Main St",
"city": "New York",
"state": "NY"
}
}
for value in find_value(json_data, "year"):
print(value)
4.如果需要读取一个非常大的文件,并对其中的每一行进行处理,但是由于文件太大,无法一次性将整个文件读入内存中。这时可以使用生成器来实现逐行读取文件并逐行处理的操作。
def process_lines(file_name):
with open(file_name) as f:
for line in f:
# 对每一行进行处理,这里只是简单地打印出来
print(line.strip())
large_file = 'data.txt'
process_lines(large_file)
5.假设有一个大型日志文件,其中包含了数千万行日志记录。需要对这个日志文件进行分析,找出所有包含特定关键字的日志记录,并进行统计。如果直接读取整个日志文件到内存中,可能会导致内存不足的问题。这时可以使用迭代器和生成器来解决这个问题。
def log_file_reader(log_file_path):
with open(log_file_path) as f:
for line in f:
yield line.strip()
def log_analyzer(log_file_path, keyword):
log_reader = log_file_reader(log_file_path)
count = 0
for line in log_reader:
if keyword in line:
count += 1
return count
log_file_path = 'logs.txt'
keyword = 'error'
error_count = log_analyzer(log_file_path, keyword)
print(f'The number of error logs is: {error_count}')
来源:https://mp.weixin.qq.com/s/g9A4rMKscHt8gKJq34sKQw
猜你喜欢
- 和以往的总监会议一样,在某个新功能的总监级别讨论会上,很多人再次又说出了同样的看法:“我们网站的界面设计太烂了,不好看、不好用、而且很乱”。
- Insert 和 Update假设现在你要把下面的数据插入到数据库中.ID = 3TheDate=mktime(0,0,0,8,31,200
- 最近研究研究了css,少不了去网上分析一下别人的网页, 但很多网站的css文件都是要么写在一行,要么一个换行都没有,看起来极其痛苦,所以写一
- asp.net的dropdownlist控件为我们的web应用提供了许多用处,但有一点我总感觉不爽的就是在使用dropdownlist的事件
- python2.7,下面是跑在window上的,稍作修改就可以跑在linux上。实测win7和raspbian均可,且raspbian可以直
- 1、定义路由// 阿里云文件储存Route::group(['prefix'=>'aliyun'],
- 前言本文主要给大家介绍了Go语言中函数new与make的使用和区别,关于Go语言中new和make是内建的两个函数,主要用来创建分配类型内存
- 一:操作redis1:redis拓展安装composer require predis/predis或者你也可以通过 PECL 安装&nbs
- 前言在Python中可迭代(Iterable)、迭代器(Iterator)和生成器(Generator)这几个概念是经常用到的,初学时对这几
- 该域名查询系统写的很简单,只是实现了功能使用XmlHttp来获取远程查询结果,实际上就是小偷程序!相关推荐:域名注册情况查询/
- 这篇文章将介绍在Python中使用 "frozenset "函数的指南,该函数返回一个新的frozenset类型的Pyt
- 五、过渡转化的使用在《mind hack》一书中,揭示了人脑鲜为人知的工作原理。其中提到了“突然的移动或闪烁会吸引人的注意力,这正是负责视觉
- 昨天打包下载了一个服务器整站,拿到这个*.mdb的文件后,却不知道怎么用,百度了一下,才知道是一种木马打包的形式文件,不能用WINrar来解
- php中可以使用 mb_detect_encoding() 函数来判断字符串是什么编码的。当在php中使用mb_detect_encodin
- 一.修改/etc/my.cnf文件default-character-set=utf8[mysqld]datadir= ar b/mysql
- 开发微信小程序过程中,有个需求需要用到日期时间筛选器,查看微信官方文档后,发现官方文档的picker筛选器只能单独支持日期或者是时间,所以为
- 近期公司准备开发一个计费项目,数据库当然还是选用我最信赖的Oracle了。由于一部分基础数据在一台Win2000 Server的S
- 这篇论坛文章(赛迪网技术社区)主要介绍了一些特别有用但文档中没有介绍的sql server DBCC命令,详细内容请参考下文:以下是一些sq
- 几个常用装饰器pytest.ini 配置文件 例子:[pytest]addopts = -v -s --html=py_test/scrip
- 在一些项目中, 我们会使用json 来将字符串转为结构体,但是很多时候,这种结构体只会用一次,基本上只会用于反序列化, 对于这种只用到一次的