python-迭代器生成器
python-迭代器生成器
python 三大利器, 迭代器,生成器和装饰器
迭代是Python中常用且非常强大的一个功能,可以被for循环的就是可迭代的,目前有字符串,列表,元组,字典,集合。 通过使用两个单独方法来实现的;它们被用于允许用户自定义类对迭代的支持。
可迭代对象iterable
是Python中一个非常庞大的概念,它主要包括如下三类
-
迭代器 (生成器)
-
序列(字符串、列表、元组)
-
字典
-
可迭代对象需要实现
__iter__
方法 -
迭代器不仅要实现
__iter__
方法,还需要实现__next__
方法 -
生成器是一个返回迭代器的函数,使用了yield,
迭代器是可迭代对象的一个子集,而生成器又是迭代器的一个子集,是一种特殊的迭代器。除了迭代器之外,Python中还有序列、字典等可迭代对象。
可迭代对象
可迭代协议: 能被for循环的就是“可迭代的”, 可迭代协议的定义:内部实现了__iter__
方法。
iterator.__iter__()
alist=[1,2]
print(alist.__iter__())
#<list_iterator object at 0x1024784a8>
返回迭代器对象本身。 如 range(),str,list,tuple,dict,set
迭代器(iterator)
l = [1,2,3]
l_iter = l.__iter__()
item = l_iter.__next__()
print(item)
item = l_iter.__next__()
print(item)
item = l_iter.__next__()
print(item)
item = l_iter.__next__()
print(item)
#
1
2
3
StopIteration
迭代器遵循迭代器协议:必须拥有__iter__
方法和__next__
方法。
如 iter(range()),iter(str),iter(list),iter(tuple),iter(dict),iter(set)
迭代器是可迭代对象的一个子集,它是一个可以记住遍历的位置的对象,它与列表、元组、集合、字符串这些可迭代对象的区别就在于next方法的实现,其他列表、元组、集合、字符串这些可迭代对象可以很简单的转化成迭代器,通过Python内置的iter函数能够轻松把可迭代对象转化为迭代器
构造迭代器iter(),next()
# 内置函数**iter()** 函数用来生成迭代器
iter(object[, sentinel])
‘‘‘输入参数
object -- 支持迭代的集合对象, 可迭代对象
sentinel -- 如果传递了第二个参数,则参数 object 必须是一个可调用的对象
‘‘‘
x_list = [1,2,3,4,5]
y_list=iter(x_List)
print(type(x_List)) # <class ‘list‘>
print(type(y_list)) # <class ‘list_iterator‘>
print(y_list)
print(next(y_list)) # <list_iterator object at 0x0000016A17F231F0>
print(next(y_list)) # 1
print(next(y_list)) # 2
# 通过iter函数把list转化成了迭代器
# 迭代器能够记住遍历位置,能够通过next方法不断从前往后访问
# 自定义类
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 # StopIteration 异常用于标识迭代的完成
myclass = MyNumbers()
myiter = iter(myclass)
print(next(myiter))
print(next(myiter))
print(next(myiter))
print(next(myiter))
print(next(myiter))
迭代器有两种:一种是调用方法直接返回的,一种是可迭代对象通过执行iter方法得到的,迭代器有的好处是可以节省内存。
生成器
生成器是迭代器的子集,换句话说,生成器一定是迭代器,但是迭代器不全是生成器对象。
- 生成器函数:常规函数定义,但是,使用yield语句而不是return语句返回结果。yield语句一次返回一个结果,在每个结果中间,挂起函数的状态,以便下次重它离开的地方继续执行
- 生成器表达式:类似于列表推导,但是,生成器返回按需产生结果的一个对象
- 本质:迭代器(所以自带了
__iter__
方法和__next__
方法,不需要我们去实现) - 特点:惰性运算,开发者自定义
在Python中,这种一边循环一边计算的机制,称为生成器:generator,生成器是一个返回迭代器的函数, 生成器是一个特殊的程序,可以被用作控制循环的迭代行为,使用yield返回值函数,每次调用yield会暂停,而可以使用next()函数和send()函数恢复生成器。
Python中的关键字yiled,在Python中一个函数可以用yiled替代return返回值,这样的话这个函数就变成了一个生成器对象
def generator(array):
for i in array:
return i
gen = generator([1,2,3,4,5])
print(type(gen))
# 输出
<class ‘int‘>
def fun_generator(array):
for i in array:
yield(i)
gen = fun_generator([1,2,3,4,5])
print(type(gen))
?
# 输出 调用一个生成器函数,返回的是一个迭代器对象。
<class ‘generator‘>
# 实例使用 yield 实现斐波那契数列
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 是一个迭代器,由生成器返回生成
while True:
try:
print (next(f), end=" ")
except StopIteration:
sys.exit()
列表推导式和生成器表达式
X = [1, 2, 3, 4, 5]
it = [i for i in X]
gen = (i for i in X)
print(type(X))
print(type(it))
print(type(gen))
# 输出
<class ‘list‘>
<class ‘list‘>
<class ‘generator‘>
# 使用中括号的叫做列表生成式, 惰性计算,延迟求值
# 获得的返回值是一个列表,而使用小括号叫做生成器表达式,获得的返回结果是一个生成器
gen = (i for i in X)
for i in gen:
print(i)
# 输出
1
2
3
4
5
应用特点
对于大数据量处理,将会非常有用。
#列表解析
sum([i for i in range(100000000)]) #内存占用大,机器容易卡死
#生成器表达式
sum(i for i in range(100000000)) #几乎不占内存
迭代器在编码方面更加简洁,这是显而易见的,其次生成器运行速度更快,最后一点,也是需要着重说明的一点:节省内存.
4G 内存处理 10G 大小的文件
# 方法1
# 仅使用 Python 内置模板,逐行读取到内存。
# 使用 yield,好处是解耦读取操作和处理操作:
def python_read(filename):
with open(filename,‘r‘,encoding=‘utf-8‘) as f:
while True:
line = f.readline()
if not line:
return
yield line
if __name__ == ‘__main__‘:
g = python_read(‘./data/movies.dat‘)
for c in g:
print(c)
# process c
方法一有缺点,逐行读入,频繁的 IO 操作拖累处理效率。
# 方法2
# 使用pandas 包 read_csv 函数,参数有 38 个之多,功能非常强大
def pandas_read(filename,sep=‘,‘,chunksize=5):
reader = pd.read_csv(filename,sep,chunksize=chunksize)
while True:
try:
yield reader.get_chunk()
except StopIteration:
print(‘---Done---‘)
break
使用如同方法一:
if __name__ == ‘__main__‘:
g = pandas_read(‘./data/movies.dat‘,sep="::")
for c in g:
print(c)
# process c