python 迭代器、生成器、yield、iter

文章目录

    • 1. 迭代器
    • 2. 生成器
    • 3. 标准库
      • 3.1 过滤
      • 3.2 映射
      • 3.3 合并
      • 3.4 排列组合
      • 3.5 重新排列
    • 4. yield from
    • 5. 可迭代的归约函数
    • 6. iter 还可以传入2个参数
    • 7. 生成器当成协程

learn from 《流畅的python》

1. 迭代器

  • 所有生成器都是迭代器,因为生成器完全实现了迭代器接口
  • 序列可以迭代的原因:iter函数,解释器需要迭代对象 x 时,会自动调用 iter(x)
  • 内置的 iter:先检查是否实现了 __iter__,不然,检查是否实现 __getitem__并创建迭代器

标准的迭代器接口有两个方法

  • __next__ 返回下一个可用的元素,如果没有元素了,抛出 StopIteration 异常
  • __iter__ 返回 self,以便在应该使用可迭代对象的地方使用迭代器,例如 在 for 循环中

不要在可迭代对象的类中实现迭代器,一举两得?错误,大佬教我不要这么做!

  • 为了支持多种遍历,需要获取独立的多个迭代器,每次调用 iter() 都创建独立的迭代器对象

可迭代的对象 一定不能自身的迭代器
也就是说,可迭代的对象 必须实现 __iter__ 方法,但不能实现 __next__ 方法

2. 生成器

只要 Python 函数的定义体中有 yield 关键字,该函数就是生成器函数
调用生成器函数时,会返回一个生成器对象

惰性获取匹配项 re.finditer ,可以节省内存和无效工作

生成器表达式可以理解为列表推导的惰性版本,按需 惰性生成元素

def genAB():print("start")yield 'A'print("continue")yield 'B'print("end")ans1 = [x*2 for x in genAB()] # 循环迭代列表推导生成的 ans1 列表
# 输出以下内容
# start
# continue
# endfor x in ans1:print(x)
# 输出
# AA
# BBans2 = (x*2 for x in genAB()) #  生成器表达式会产出生成器,ans2 是一个生成器对象
# 无输出for x in ans2: # 调用时,才真正执行 genAB 函数产出数值print(x)
# 输出
# start
# AA
# continue
# BB
# end

3. 标准库

import itertools
gen = itertools.count(5, 0.5)
print(next(gen))
print(next(gen))
print(next(gen))
# 5
# 5.5
# 6.0
  • list(count()) 会生成无穷的序列,内存会爆炸
gen = itertools.takewhile(lambda n : n < 6, itertools.count(5, 0.5))
print(list(gen)) # [5, 5.5]
  • takewhile 不满足条件时退出

3.1 过滤

在这里插入图片描述

def vowel(c):return c.lower() in "aeiou"print(list(filter(vowel, "Abcdea")))  # ['A', 'e', 'a']
print(list(itertools.filterfalse(vowel, "Abcdea")))  # ['b', 'c', 'd']
print(list(itertools.dropwhile(vowel, "Aardvark")))
# ['r', 'd', 'v', 'a', 'r', 'k'] 遇到不满足的即停止检测
print(list(itertools.takewhile(vowel, "Aardvark")))
# ['A', 'a']  遇到不满足的即停止检测
print(list(itertools.compress('Aardvark', (1, 0, 1, 1, 0, 1))))
# 产出后者是真值的前者元素 ['A', 'r', 'd', 'a']
print(list(itertools.islice('Aardvark', 4)))
# ['A', 'a', 'r', 'd'] 前 4 个元素
print(list(itertools.islice('Aardvark', 4, 7)))
# ['v', 'a', 'r'] [4,7) 的元素
print(list(itertools.islice('Aardvark', 1, 7, 2)))
# ['a', 'd', 'a'] [1,7) 每 2 个 取一个

3.2 映射

在这里插入图片描述

sample = [9, 5, 4, 6, 8, 9]
print(list(itertools.accumulate(sample)))
# [9, 14, 18, 24, 32, 41] 累加求和,前缀和
print(list(itertools.accumulate(sample, min)))
# [9, 5, 4, 4, 4, 4] 累积的最小值
print(list(itertools.accumulate(sample, max)))
# [9, 9, 9, 9, 9, 9]
print(list(itertools.accumulate(sample, operator.mul)))
# [9, 45, 180, 1080, 8640, 77760] 前缀乘积
print(list(itertools.accumulate(range(1, 11), operator.mul)))
# [1, 2, 6, 24, 120, 720, 5040, 40320, 362880, 3628800]
print(list(enumerate("abc", start=2)))
# [(2, 'a'), (3, 'b'), (4, 'c')]
print(list(map(operator.mul, range(11), range(1, 11))))
# x*(x+1) 对应相乘,元素少的结束即停止
print(list(map(lambda a, b: (a, b), range(11), [2, 4, 8])))
# [(0, 2), (1, 4), (2, 8)] 等效于 zip 函数
print(list(itertools.starmap(operator.mul, enumerate('abc', 1))))
# ['a', 'bb', 'ccc']
sample = [2, 3, 4, 5]
print(list(itertools.starmap(lambda a, b: b / a, enumerate(itertools.accumulate(sample), 1))))
# 求累积 均值 [2.0, 2.5, 3.0, 3.5]

3.3 合并

在这里插入图片描述

print(list(itertools.chain("ABC", range(5))))
# ['A', 'B', 'C', 0, 1, 2, 3, 4] , 可传入多个可迭代对象
print(list(itertools.chain(enumerate('ABC'))))
# [(0, 'A'), (1, 'B'), (2, 'C')] 传入一个参数,没啥用
print(list(itertools.chain.from_iterable(enumerate('ABC'))))
# 只接收一个参数,且对象是可迭代的
# [0, 'A', 1, 'B', 2, 'C']
print(list(zip('ABC', range(5))))
# [('A', 0), ('B', 1), ('C', 2)] 短的先结束
print(list(zip('ABC', range(5), [10, 20, 30, 40])))
# [('A', 0, 10), ('B', 1, 20), ('C', 2, 30)] 课输入多个参数
print(list(itertools.zip_longest('ABC', range(5))))
# [('A', 0), ('B', 1), ('C', 2), (None, 3), (None, 4)], 以最长的为结束
print(list(itertools.zip_longest('ABC', range(5), fillvalue='?')))
# [('A', 0), ('B', 1), ('C', 2), ('?', 3), ('?', 4)] 填充默认值
# 笛卡尔积,惰性生成
print(list(itertools.product('ABC', range(2))))
# [('A', 0), ('A', 1), ('B', 0), ('B', 1), ('C', 0), ('C', 1)]
print(list(itertools.product('ABC')))
# [('A',), ('B',), ('C',)] 传入一个参数,得到只有一个元素的元组,没啥用
print(list(itertools.product('ABC', repeat=2)))
# [('A', 'A'), ('A', 'B'), ('A', 'C'), ('B', 'A'), ('B', 'B'), ('B', 'C'), ('C', 'A'), ('C', 'B'), ('C', 'C')]
# 相当于两重循环
print(list(itertools.product(range(2), repeat=3)))
# [(0, 0, 0), (0, 0, 1), (0, 1, 0), (0, 1, 1), (1, 0, 0), (1, 0, 1), (1, 1, 0), (1, 1, 1)]
# 3 重循环
rows = itertools.product('AB', range(2), repeat=2)
for row in rows: print(row)
# ('A', 0, 'A', 0)
# ('A', 0, 'A', 1)
# ('A', 0, 'B', 0)
# ('A', 0, 'B', 1)
# ('A', 1, 'A', 0)
# ('A', 1, 'A', 1)
# ('A', 1, 'B', 0)
# ('A', 1, 'B', 1)
# ('B', 0, 'A', 0)
# ('B', 0, 'A', 1)
# ('B', 0, 'B', 0)
# ('B', 0, 'B', 1)
# ('B', 1, 'A', 0)
# ('B', 1, 'A', 1)
# ('B', 1, 'B', 0)
# ('B', 1, 'B', 1)
print("-----")
for a in "AB":for b in range(2):for c in "AB":for d in range(2):print((a, b, c, d))
# ('A', 0, 'A', 0)
# ('A', 0, 'A', 1)
# ('A', 0, 'B', 0)
# ('A', 0, 'B', 1)
# ('A', 1, 'A', 0)
# ('A', 1, 'A', 1)
# ('A', 1, 'B', 0)
# ('A', 1, 'B', 1)
# ('B', 0, 'A', 0)
# ('B', 0, 'A', 1)
# ('B', 0, 'B', 0)
# ('B', 0, 'B', 1)
# ('B', 1, 'A', 0)
# ('B', 1, 'A', 1)
# ('B', 1, 'B', 0)
# ('B', 1, 'B', 1) 跟上面结果一致

在这里插入图片描述

ct = itertools.count()
print(next(ct), next(ct), next(ct), next(ct), next(ct))
# 0 1 2 3 4
print(list(itertools.islice(itertools.count(1, .3), 3)))
# [1, 1.3, 1.6]
cy = itertools.cycle('ABC')
print(next(cy), next(cy), next(cy), next(cy))
# A B C A, 产生元素的副本,不断重复
print(list(itertools.islice(cy, 7)))
# ['B', 'C', 'A', 'B', 'C', 'A', 'B']
rp = itertools.repeat(7)
print(list(itertools.islice(rp, 10)))
# [7, 7, 7, 7, 7, 7, 7, 7, 7, 7]
print(list(itertools.repeat(8, 4)))
# [8, 8, 8, 8]
print(list(map(operator.mul, range(11), itertools.repeat(5))))
# [0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50] 0-10 分别乘以5

3.4 排列组合

print(list(itertools.combinations("ABC", 2)))
# [('A', 'B'), ('A', 'C'), ('B', 'C')]
# 组合:从中取出2个的方案数,无序要求 C32
print(list(itertools.combinations_with_replacement("ABC", 2)))
# [('A', 'A'), ('A', 'B'), ('A', 'C'), ('B', 'B'), ('B', 'C'), ('C', 'C')]
# 组合:无序,可重复
print(list(itertools.permutations("ABC", 2)))
# [('A', 'B'), ('A', 'C'), ('B', 'A'), ('B', 'C'), ('C', 'A'), ('C', 'B')]
# 排列:有顺序要求
print(list(itertools.product("ABC", repeat=2))) # 的笛卡儿积
# [('A', 'A'), ('A', 'B'), ('A', 'C'),
#  ('B', 'A'), ('B', 'B'), ('B', 'C'),
#  ('C', 'A'), ('C', 'B'), ('C', 'C')]

3.5 重新排列

在这里插入图片描述

print(list(itertools.groupby("LLLLAAGGG")))
# [('L', <itertools._grouper object at 0x000001A6D638C460>),
#  ('A', <itertools._grouper object at 0x000001A6D6538E80>),
#  ('G', <itertools._grouper object at 0x000001A6D8F7EA00>)]
for char, group in itertools.groupby("LLLLAAGGG"):print(char, "->", list(group))# L -> ['L', 'L', 'L', 'L']
# A -> ['A', 'A']
# G -> ['G', 'G', 'G']for char, group in itertools.groupby("ALLLLAAGGG"):print(char, "->", list(group))
# A -> ['A']  # 没有相邻的A
# L -> ['L', 'L', 'L', 'L']
# A -> ['A', 'A']
# G -> ['G', 'G', 'G']animals = ['duck', 'eagle', 'rat', 'giraffe', 'bear', 'bat', 'dolphin', 'shark', 'lion']
animals.sort(key=len)  # 按长度排序
print(animals)
# ['rat', 'bat', 'duck', 'bear', 'lion', 'eagle', 'shark', 'giraffe', 'dolphin']
for length, group in itertools.groupby(animals, len):print(length, "->", list(group))
# 3 -> ['rat', 'bat']
# 4 -> ['duck', 'bear', 'lion']
# 5 -> ['eagle', 'shark']
# 7 -> ['giraffe', 'dolphin']
for length, group in itertools.groupby(reversed(animals), len):print(length, "->", list(group))
# 7 -> ['dolphin', 'giraffe']
# 5 -> ['shark', 'eagle']
# 4 -> ['lion', 'bear', 'duck']
# 3 -> ['bat', 'rat']
abc = ["apple", "bear", "animals", "bull", "lakers"]
abc.sort()
for char, group in itertools.groupby(abc, lambda x: x[0]):print(char, "->", list(group))
# 按首字母分组
# a -> ['animals', 'apple']
# b -> ['bear', 'bull']
# l -> ['lakers']
# itertools.tee 函数产出多个生成器,每个生成器都 可以产出输入的各个元素
# 默认2个,后面可加参数 n, 输出多个
print(list(itertools.tee("ABC")))
# [<itertools._tee object at 0x000001D4AEEE8AC0>, 
#  <itertools._tee object at 0x000001D4AEEE8A80>]
g1, g2 = itertools.tee("ABC")
print(next(g1))  # A
print(list(g1))  # ['B', 'C']
print(next(g2), next(g2))  # A B
print(list(g2))  # ['C']
print(list(zip(*itertools.tee('ABC'))))
# [('A', 'A'), ('B', 'B'), ('C', 'C')]

4. yield from

yield from 语句的作用就是把不同的生成器结合在一起使用

def chain(*iterables):for it in iterables:for i in it:yield i
s = "ABC"
t = tuple(range(3))
print(list(chain(s, t)))
# ['A', 'B', 'C', 0, 1, 2]def chain1(*iterables):for it in iterables:yield from it# 完全代替了内层的 for 循环
print(list(chain1(s, t)))
# ['A', 'B', 'C', 0, 1, 2]

5. 可迭代的归约函数

在这里插入图片描述

  • any, all 可以短路,一旦确定结果,就停止迭代
  • 也可以这样调用 max(arg1, arg2, ..., [key=?])
  • sorted 操作完成后返回排序后的 列表。它可以处理任意的可迭代对象
print(all([1, 2, 3]))  # True
print(all([0, 2, 3]))  # False
print(all([]))  # True
print(any([1, 2, 3]))  # True
print(any([0, 2, 3]))  # True
print(any([0, 0.0]))  # False
print(any([]))  # False
g = (n for n in [0, 0.0, 7, 8])
print(any(g))  # True 遇到7结束
print(list(g))  # [8] 还剩余8

6. iter 还可以传入2个参数

  • 当遇到第二个参数时停止迭代
def d6():return random.randint(1, 6)d6_iter = iter(d6, 1)  # 无参函数, 遇到1停止迭代
for roll in d6_iter:print(roll)
# 6
# 2
# 4
# 3
# 2
# 4
# 3
# 5
# 2
# 3
print(list(d6_iter)) # [] 耗尽了
d6_iter = iter(d6, 1)
print(list(d6_iter)) # [4, 5, 3, 6, 2, 5, 4, 6, 5, 6, 6] 随机的

这段代码逐行读取文件,直到遇到空行或者到达文件末尾为止

with open('mydata.txt') as fp:for line in iter(fp.readline, '\n'):process_line(line)

7. 生成器当成协程

  • .send() 方法,后面会学到
  • .__next__() 方法一样,.send() 方法致使生成器前进到下一个 yield 语句
  • .send() 方法还允许使用生成器的客户 把 数据 发给 自己,即不管传给 .send() 方法什么参数,那个参数都会 成为生成器 函数定义体中对应的 yield 表达式的值

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

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

相关文章

java微信学习 接入

现在实习的公司要做微信开发&#xff0c;然而一直没安排任务&#xff0c;所以一直在看微信接口&#xff0c;记录下学习的内容 微信开发肯定要看的就是微信公众平台开发者文档&#xff0c;上面有每种接口的调用格式&#xff0c;刚开始学习的时候自己申请了一个订阅号&#xff0c…

LeetCode 1976. 到达目的地的方案数(迪杰斯特拉 Python 优先队列)

文章目录1. 题目2. 解题1. 题目 你在一个城市里&#xff0c;城市由 n 个路口组成&#xff0c;路口编号为 0 到 n - 1 &#xff0c;某些路口之间有 双向 道路。 输入保证你可以从任意路口出发到达其他任意路口&#xff0c;且任意两个路口之间最多有一条路。 给你一个整数 n 和…

c++ sendmessage 鼠标 坐标是相对自身吗_【科普】你真的足够了解五轴加工吗?看完豁然开朗!...

近年来五轴联动数控加工中心在各领域得到了越来越广泛的应用。在实际应用中&#xff0c;每当人们碰见异形复杂零件高效、高质量加工难题时&#xff0c;五轴联动技术无疑是解决这类问题的重要手段。越来越多的厂家倾向于寻找五轴设备来满足高效率、高质量的加工。但是&#xff0…

32g内存 android开发,16G走开 我要32G内存的安卓手机

对于很多用户来说&#xff0c;在准备换手机的时候最纠结的莫过于是选择16G的还是32G的&#xff0c;毕竟价格相差好几百&#xff0c;但这里给你的建议是买32G的&#xff0c;即使贵点&#xff0c;但长远来说&#xff0c;是利大于弊的&#xff0c;为什么这么说呢&#xff0c;且听小…

andriod studio 运行 无结果_无负压静音供水设备下篇一

1、无负压静音供水设备的安全接地保护a )控制柜的金属柜体上应有可靠的接地保护&#xff0c;与接地点相连的保护导线的截面应符合GB/T3797-2005中4.10.6的规定。与接地点连接的导线必须是黄、绿双色或铜编织线&#xff0c;并有明显的接地标识。a) 主接地点与设备任何有关的、因…

html设置div页面最底,使用css让大图片不超过网页宽度

让大图片不超过网页宽度&#xff0c;让图片不撑破通过CSS样式设置的DIV宽度&#xff01;接下来&#xff0c;我们来介绍下网站在开发DIVCSS的时候会遇到一个问题&#xff0c;在发布一个大图片的时候因为图片过宽会撑破自己设置的div宽度的问题。图片撑破布局原因1、由于浏览器版…

java上机题四取三排列_java语言特性概述

一.前言 我们都知道java是面向对象的编程&#xff0c;其中四个基本特性&#xff1a;抽象、封装、继承、多态。这四个特性&#xff0c;概括起来可以这么理解&#xff0c;抽象、封装、继承是多态的基础&#xff0c;多态是抽象、封装、继承的表现。二. JAVA 语言特点 a) 跨平台&am…

LeetCode 1984. 学生分数的最小差值

文章目录1. 题目2. 解题1. 题目 给你一个 下标从 0 开始 的整数数组 nums &#xff0c;其中 nums[i] 表示第 i 名学生的分数。另给你一个整数 k 。 从数组中选出任意 k 名学生的分数&#xff0c;使这 k 个分数间 最高分 和 最低分 的 差值 达到 最小化 。 返回可能的 最小差…

C++中vector使用详细说明 (转)

转自&#xff1a;http://blog.chinaunix.net/uid-26000296-id-3785610.html http://www.cnblogs.com/mr-wid/archive/2013/01/22/2871105.html 一、向量的介绍 向量 vector 是一种对象实体, 能够容纳许多其他类型相同的元素, 因此又被称为容器。 与string相同, vector 同属于…

c++ 一行输出八个数字_R语言笔记(三):数据输入与输出

本文主要介绍数据基本的输入与输出方法&#xff0c;内容包括&#xff1a;1. 数据的输入1.1 scan(), edit(), fix()1.2 调用 R 包自带数据1.3 调用本地数据2. 数据的输出1. 数据的输入1.1 scan(), edit(), fix()手动输入数据主要有以下几种方式&#xff1a;x <- c() # c() 进…

LeetCode 1985. 找出数组中的第 K 大整数(排序)

文章目录1. 题目2. 解题1. 题目 给你一个字符串数组 nums 和一个整数 k 。 nums 中的每个字符串都表示一个不含前导零的整数。 返回 nums 中表示第 k 大整数的字符串。 注意&#xff1a;重复的数字在统计时会视为不同元素考虑。 例如&#xff0c;如果 nums 是 [“1”,“2”,…

firefox应用自动全屏显示_【b】—自动化测试:基础selenium—API

一、浏览器对象# 导入webdriverfrom selenium import webdriver# 创建一个浏览器对象driver webdriver.Firefox()# 设置全屏# driver.maximize_window()# 获取当前浏览器尺寸# size driver.get_window_size()# print(size)# 设置浏览器尺寸driver.set_window_size(400, 400)s…

【linux高级程序设计】(第十三章)Linux Socket网络编程基础 2

BSD Socket网络编程API 创建socket对象 int socket (int __domain, int __type, int __protocol) &#xff1a;成功返回socket文件描述符&#xff0c;失败返回-1. 参数1&#xff1a;socket对象使用的地址簇或协议簇 常用的有PF_LOCAL(本机通信)、PF_INET(IPv4协议簇)、PF_INET6…

数据库中有痣但是有时取不到_农村这种长得像“泥鳅”的鱼,以前没人吃,现在可能有钱都吃不到...

只说真话的农民公众号原创文章&#xff0c;严禁转载在农村中有很多不能叫出名字的花草和野味&#xff0c;它们当中虽然有些长得比较奇怪&#xff0c;名字也比较奇怪&#xff0c;但是却是非常好的疗补食物。有些花草是治疗疾病的良药&#xff0c;有些野味现在也被搬上了酒桌。但…

python 使用 asyncio 包处理并发

文章目录1. 线程与协程对比2. 使用 asyncio 和 aiohttp 下载3. 避免阻塞型调用4. 使用 asyncio.as_completed5. 使用Executor对象&#xff0c;防止阻塞事件循环6. 从回调到期物和协程learn from 《流畅的python》 1. 线程与协程对比 threading import threading import iter…

LeetCode 1991. 找到数组的中间位置(前缀和)

文章目录1. 题目2. 解题1. 题目 给你一个下标从 0 开始的整数数组 nums &#xff0c;请你找到 最左边 的中间位置 middleIndex &#xff08;也就是所有可能中间位置下标最小的一个&#xff09;。 中间位置 middleIndex 是满足 nums[0] nums[1] ... nums[middleIndex-1] n…

LeetCode 1992. 找到所有的农场组(BFS)

文章目录1. 题目2. 解题1. 题目 给你一个下标从 0 开始&#xff0c;大小为 m x n 的二进制矩阵 land &#xff0c;其中 0 表示一单位的森林土地&#xff0c;1 表示一单位的农场土地。 为了让农场保持有序&#xff0c;农场土地之间以矩形的 农场组 的形式存在。 每一个农场组都…

VS2015开发Android,自带模拟器无法调试、加载程序,算是坑吗

VS2015出来后&#xff0c;确定变化很大&#xff0c;什么android、ios的&#xff0c;不在话下。对于我这样传统型的人&#xff0c;也第一时间试用了一下&#xff08;vs2003->vs2008->vs2012->vs2015&#xff09;。以前用eclipse开发过android小程序&#xff0c;现在想试…

amd cpu 安卓模拟器_夜神模拟器常见问题解答_v20201025

MAC版本常见问题Mac版本模拟器常见问题MAC模拟器出现“您应该将它移到废纸篓”解决办法MAC版本模拟器功能介绍MAC版本模拟器界面Mac版模拟器可能无法启动(卡99%)的原因及解决方式其他问题如何在夜神模拟器中安装自己想要的游戏/应用Sample CA 2证书没网解决办法GlobalSignature…

LeetCode 502. IPO(优先队列)

文章目录1. 题目2. 解题1. 题目 假设 力扣&#xff08;LeetCode&#xff09;即将开始 IPO 。 为了以更高的价格将股票卖给风险投资公司&#xff0c;力扣 希望在 IPO 之前开展一些项目以增加其资本。 由于资源有限&#xff0c;它只能在 IPO 之前完成最多 k 个不同的项目。 帮助…