迭代对象 迭代器 生成器

python 迭代对象 迭代器 生成器区别

以上三者和容器分不开。容器是一种把多个元素组织在一起的数据结构,容器中的元素可以逐个地迭代获取,可以用in, not in关键字判断元素是否包含在容器中。

迭代对象 Iterable

硬性规定就是

  • 实现了
__iter__() 

方法的就是迭代对象。通过 Iterable 判断是否是迭代对象。

>>> dic = {'a': aa}
>>> from collections import Iterable
>>> print isinstance(dic, Iterable)
True
>>> dir(dic)
['__class__', '__cmp__', '__contains__', '__delattr__', '__delitem__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'clear', 'copy', 'fromkeys', 'get', 'has_key', 'items', 'iteritems', 'iterkeys', 'itervalues', 'keys', 'pop', 'popitem', 'setdefault', 'update', 'values', 'viewitems', 'viewkeys', 'viewvalues']

>>> from collections import Iterator
>>> print isinstance(dic, Iterator)
False
>>>

可以看到确实实现了相应的方法。并且可以看到他不是迭代器。迭代器下面会说到。

迭代器 Iterator

  • 实现了
__iter__()
__next__()

返回当前的元素,并指向下一个元素的位置,当前位置已经没有元素的时候,抛出StopIteration异常。

from collections import Iterable
from collections import Iterator


class MyRange(object):
    def __init__(self, n):
        self.idx = 0
        self.n = n

    def __iter__(self):
        return self

    def next(self):
        if self.idx < self.n:
            val = self.idx
            self.idx += 1
            return val
        else:
            raise StopIteration()


if __name__ == '__main__':
    myRange = MyRange(4)
    print type(myRange)
    for i in myRange:
        print i

    print isinstance(myRange, Iterable)
    print isinstance(myRange, Iterator)

结果为

<class '__main__.MyRange'>
0
1
2
3
True
True

可以看到实现了这两个方便确实是迭代器了.

  • 凡是可作用于for循环的对象都是Iterable类型
  • 凡是可作用于next()函数的对象都是Iterator类型,它们表示一个惰性计算的序列;
  • 集合数据类型如list、dict、str等是Iterable但不是Iterator,不过可以通过iter()函数获得一个Iterator对象。

生成器

生成器个人的理解有点像把函数当成了对象的概念。使用yield 这个关键字返回函数当前的一个状态值。并且函数内容不会释放掉。这样变量也没有释放。而yield相当于debug中的断点。return了一个值,后面再从这里开始运行,再次停在yield这个关键词上去。而yield关键字还可以通过send来设置当前这个变量的值,相当于从外部传入。

def func(n):
    yield n*2
    
g = func(5)
print 'g type:%s' % type(g)
for i in g:
    print i

func 就是一个生成器函数,调用该函数时返回对象就是生成器 g ,这个生成器对象的行为和迭代器是非常相似的,可以用在 for 循环等场景中。注意 yield 对应的值在函数被调用时不会立刻返回,而是调用next方法时(本质上 for 循环也是调用 next 方法)才返回

为什么用生成器取代列表

 L = [x * x for x in range(10)]
 g = (x * x for x in range(10))

创建L和g的区别仅在于最外层的[]和(),L是一个list,而g是一个generator。

不同的是如果range 是10w,则L包含了10万个元素。但是g只是包含了一个元素。当只需要遍历的时候无需记住每一个值是什么,使用g显然更加的合理。

def fib(max):
    n, a, b = 0, 0, 1
    while n < max:
        yield b
        a, b = b, a + b
        n = n + 1
        
if __name__ == '__main__':
     f = fib(6)
        for i in f:
            print i
            
###############
1
1
2
3
5
8

关于send操作暂时接触不多…
廖雪峰 生成器

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值