Python中迭代器与生成器的用法
作者:springsnow 发布时间:2021-08-30 00:53:18
一、迭代器(foreach)
1、可迭代的对象
内置有__iter__
方法的都叫可迭代的对象。
Python内置str、list、tuple、dict、set、file都是可迭代对象。
x = 1.__iter__ # SyntaxError: invalid syntax
# 以下都是可迭代的对象
name = 'nick'.__iter__
print(type(name)) # 'method-wrapper'>
2、迭代器对象
执行可迭代对象的__iter__
方法,拿到的返回值就是迭代器对象。
只有字符串和列表都是依赖索引取值的,而其他的可迭代对象都是无法依赖索引取值的,只能使用迭代器对象。
内置有
__iter__
方法,执行该方法会拿到迭代器本身。内置
__next__
方法,执行该方法会拿到迭代器对象中的一个值。
s = 'hello'
iter_s = s.__iter__()
print(type(iter_s)) # 'str_iterator'> iter_s为迭代器对象
while True:
try:
print(iter_s.__next__())
except StopIteration:
break
#hello
3、迭代器有两个基本的方法:iter() 和 next()。
s = 'hello'
iter_s = iter(s) # 创建迭代器对象
print(type(iter_s)) # iter_s为迭代器对象
while True:
try:
print(next(iter_s)) # 输出迭代器的下一个元素
except StopIteration:
break
# hello
4、for迭代器循环
可迭代对象可以直接使用常规for语句进行遍历
for循环称为迭代器循环,in后必须是可迭代的对象。
#str
name = 'nick'
for x in name:
print(x)
#list
for x in [None, 3, 4.5, "foo", lambda: "moo", object, object()]:
print("{0} ({1})".format(x, type(x)))
#dict
d = {
'1': 'tasty',
'2': 'the best',
'3 sprouts': 'evil',
'4': 'pretty good'
}
for sKey in d:
print("{0} are {1}".format(sKey, d[sKey]))
#file
f = open('32.txt', 'r', encoding='utf-8')
for x in f:
print(x)
f.close()
5、实现迭代器(__next__和__iter__)
把一个类作为一个迭代器使用需要在类中实现两个方法 __iter__() 与 __next__() 。
__iter__() 方法返回一个特殊的迭代器对象, 这个迭代器对象实现了 __next__() 方法并通过 StopIteration 异常标识迭代的完成。
__next__() 方法会返回下一个迭代器对象。
StopIteration 异常用于标识迭代的完成,防止出现无限循环的情况,在 __next__() 方法中我们可以设置在完成指定循环次数后触发 StopIteration 异常来结束迭代。
创建一个返回数字的迭代器,初始值为 1,逐步递增 1,在 20 次迭代后停止执行:
class MyNumbers:
def __iter__(self):
self.a = 1
return self
def __next__(self):
if self.a <= 20:
x = self.a
self.a += 1
return x
else:
raise StopIteration
myclass = MyNumbers()
myiter = iter(myclass)
for x in myiter:
print(x)
1、模拟range
class Range:
def __init__(self, n, stop, step):
self.n = n
self.stop = stop
self.step = step
def __next__(self):
if self.n >= self.stop:
raise StopIteration
x = self.n
self.n += self.step
return x
def __iter__(self):
return self
for i in Range(1, 7, 3):
print(i)
#1
#4
2、斐波那契数列
class Fib:
def __init__(self):
self._a = 0
self._b = 1
def __iter__(self):
return self
def __next__(self):
self._a, self._b = self._b, self._a + self._b
return self._a
f1 = Fib()
for i in f1:
if i > 100:
break
print('%s ' % i, end='')
# 1 1 2 3 5 8 13 21 34 55 89
二、生成器
1、yield
在 Python 中,使用了 yield 的函数被称为生成器(generator)。
跟普通函数不同的是,生成器是一个返回迭代器的函数,只能用于迭代操作,更简单点理解生成器就是一个迭代器。
在调用生成器运行的过程中,每次遇到 yield 时函数会暂停并保存当前所有的运行信息,返回 yield 的值, 并在下一次执行 next() 方法时从当前位置继续运行。
调用一个生成器函数,返回的是一个迭代器对象。
yield后面可以加多个数值(可以是任意类型),但返回的值是元组类型的。
提供一种自定义迭代器的方式
yield可以暂停住函数,并提供当前的返回值
import sys
def fibonacci(n): # 函数 - 斐波那契
a, b, counter = 0, 1, 0
while True:
if counter > n:
return
yield a
a, b = b, a + b
counter += 1
f = fibonacci(10) #f 是一个生成器
print(type(f)) # 'generator'>
while True:
try:
print(next(f), end=" ")
except StopIteration:
sys.exit()
yield和return:
相同点:两者都是在函数内部使用,都可以返回值,并且返回值没有类型和个数的限制
不同点:return只能返回一次值;yield可以返回多次值
2、自定义range()方法
def my_range(start, stop, step=1):
while start < stop:
yield start
start += 1
g = my_range(0, 3)
print(f"list(g): {list(g)}")
复杂版本:
def range(*args, **kwargs):
if not kwargs:
if len(args) == 1:
count = 0
while count < args[0]:
yield count
count += 1
if len(args) == 2:
start, stop = args
while start < stop:
yield start
start += 1
if len(args) == 3:
start, stop, step = args
while start < stop:
yield start
start += step
else:
step = 1
if len(args) == 1:
start = args[0]
if len(args) == 2:
start, stop = args
for k, v in kwargs.items():
if k not in ['start', 'step', 'stop']:
raise ('参数名错误')
if k == 'start':
start = v
elif k == 'stop':
stop = v
elif k == 'step':
step = v
while start < stop:
yield start
start += step
for i in range(3):
print(i) # 0,1,2
for i in range(99, 101):
print(i) # 99,100
for i in range(1, 10, 3):
print(i) # 1,4,7
for i in range(1, step=2, stop=5):
print(i) # 1,3
for i in range(1, 10, step=2):
print(i) # 1,3,5,7,9
3、生成器表达式(i.for .in)
把列表推导式的[]换成()就是生成器表达式 。
优点:比起列表推导式,可以省内存,一次只产生一个值在内存中
t = (i for i in range(10))
print(t) # <generator object at 0x00000000026907B0>
print(next(t)) # 0
print(next(t)) # 1
举例:
with open('32.txt', 'r', encoding='utf8') as f:
nums = [len(line) for line in f] # 列表推导式相当于直接给你一筐蛋
print(max(nums)) # 2
with open('32.txt', 'r', encoding='utf8') as f:
nums = (len(line) for line in f) # 生成器表达式相当于给你一只老母鸡。
print(max(nums)) # ValueError: I/O operation on closed file.
来源:https://www.cnblogs.com/springsnow/p/12053195.html
猜你喜欢
- 最近在学爬虫时发现许多网站都有自己的反爬虫机制,这让我们没法直接对想要的数据进行爬取,于是了解这种反爬虫机制就会帮助我们找到解决方法。常见的
- 本文实例讲述了python中argparse模块用法。分享给大家供大家参考。具体分析如下:平常在写命令行工具的时候,经常会带参数,所以用py
- 本文实例讲述了PHP简单实现正则匹配省市区的方法。分享给大家供大家参考,具体如下:省市区正则匹配preg_match('/(.*?(
- 内容摘要: 网页的色彩搭配往往是网友们感到头疼的问题,尤其是那些完全没有美术基础的网友。到底用
- ASP+Access数据库的18条安全法则:1.首先,我们需要过滤所有客户端提交的内容,其中包括?id=N一类,另外还有提交的html代码中
- 想查找mac下python的site-packages目录,如果用网上搜的安装目录之类的去找,进去每一层很多都是软链接形式存在,比较浪费时间
- 如何使DIV居中,div垂直居中,div水平居中.这个问题在用CSS来设计网页的时候经常会遇到,如果用传统的表格来布局是很简单的,CSS里就
- MySQL出错代码列表:1005:创建表失败1006:创建数据库失败1007:数据库已存在,创建数据库失败1008:数据库不存在,删除数据库
- class ascii{function decode($str){ preg_match_all( &
- 本文为大家分享了windows下pycharm安装、创建文件、配置默认模板的具体步骤,供大家参考,具体内容如下步骤: 下包 —->安装
- 如何在VSCode中添加Python解释器并安装Python库一. 安装VScode编辑器双击“VSCodeUserSe
- 如下所示:alist=[1,2]] >>>[1,2] alist.append([3,4]) >>>[1
- 相信大家在爬虫中都设置过请求头 user-agent 这个参数吧? 在请求的时候,加入这个参数,就可以一定程度的伪装成浏览器,就不会被服务器
- 去空格函数有如下两种:·LTRIM()LTRIM() 函数把字符串头部(左)的空格去掉,其语法如下:LTRIM (<character
- 本文记录了如何在Pytorch中使用Tensorboard(主要是为了备忘)前言虽然我本身就会用TensorBoard,但是因为Tensor
- 问题我试图打印some_cell.font.color.rgb并得到各种结果。对于一些人,我得到了我想要的东西(比如“ FF000000”)
- 元组是不可变的Python对象序列。元组的序列就像列表。唯一的区别是,元组不能被改变,即元组是不可被修改。元组使用小括号,而列表
- 项目演示:一、输入金额二、跳转到支付宝付款三、支付成功四、跳转回自己网站在使用支付宝接口的前期准备:1、支付宝公钥2、应用公钥3、应用私钥4
- from flask import requestFlask 是一个人气非常高的Python Web框架,笔者也拿它写过一些大大小小的项目,
- 如果你从来没有使用过Python,我强烈建议你阅读Python introduction,因为你需要知道基本的语法和类型。包管理Python