python-迭代器生成器

时间:2021-07-05 16:49:24   收藏:0   阅读:0

python-迭代器生成器

python 三大利器, 迭代器,生成器和装饰器

迭代是Python中常用且非常强大的一个功能,可以被for循环的就是可迭代的,目前有字符串,列表,元组,字典,集合。 通过使用两个单独方法来实现的;它们被用于允许用户自定义类对迭代的支持。

可迭代对象iterable 是Python中一个非常庞大的概念,它主要包括如下三类

迭代器是可迭代对象的一个子集,而生成器又是迭代器的一个子集,是一种特殊的迭代器。除了迭代器之外,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方法得到的,迭代器有的好处是可以节省内存。

生成器

生成器是迭代器的子集,换句话说,生成器一定是迭代器,但是迭代器不全是生成器对象。

在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

评论(0
© 2014 mamicode.com 版权所有 京ICP备13008772号-2  联系我们:gaon5@hotmail.com
迷上了代码!