Python Iterator 学习小记

Python Iterator 学习小记

The reference link: Implicit sequences by cs61a

Iterator

Python提供了一种统一的方式来顺序处理容器值(container value)的元素(elements),称为迭代器(Iterator)。迭代器是一个对象(Object),它提供对值(values)的顺序访问。

primes = [2, 3, 5, 7]
type(primes)
<class 'list'>
iterator = iter(primes)
type(iterator)
<class 'list_iterator'>
next(iterator)
2
>>> next(iterator)
3
>>> next(iterator)
5

当Iterator处在最后一个元素时调用next(iterator),Python会引发StopIteration异常(exception)。

>>> next(iterator)
7
>>> next(iterator)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration
>>> try:
        next(iterator)
    except StopIteration:
        print('No more values')
No more values

我们可以将Iterator赋值给另一个变量:

>>> r = range(3, 13)
>>> s = iter(r)  # 1st iterator over r
>>> next(s)
3
>>> next(s)
4
>>> t = iter(r)  # 2nd iterator over r
>>> next(t)
3
>>> next(t)
4
>>> u = t        # Alternate name for the 2nd iterator
>>> next(u)
5
>>> next(u)
6

注意,赋值并非c++中的复制(copy),而是绑定(binding),即上例中的ut指向同一个Iterator。

Iterables

任何可以产生Iterator的值都称为可迭代值(Iterable value)。在Python中,可迭代值是任何可以传递给内置iter函数的值。可迭代对象包括序列值,如list和tuple,以及其他容器,如set和dictionary。Iterator也iterable,因为它们可以传递给iter函数。

>>> d = {'one': 1, 'two': 2, 'three': 3}
>>> d
{'one': 1, 'three': 3, 'two': 2}
>>> k = iter(d)
>>> next(k)
'one'
>>> next(k)
'three'
>>> v = iter(d.values())
>>> next(v)
1
>>> next(v)
3

注意
dict是(在python3.6及之后版本)是有序的,其key、value和item都是iterable。

For statement

for的本质生成一个iterator并迭代。

>>> counts = [1, 2, 3]
>>> for item in counts:
        print(item)
1
2
3

它可以写成这样:

>>> items = counts.__iter__()
>>> try:
        while True:
            item = items.__next__()
            print(item)
    except StopIteration:
        pass
1
2
3

我们用except处理StopIteration异常但不做任何处理。
注意:iter函数本质是调用Class里的内置__iter__函数,next同理,故iter(counts)counts.__iter__()等价。

Generators and Yield Statements

生成器(Generator)是由一种称为生成器(generator function)函数的特殊函数类返回的Iterator。生成器函数与常规函数的区别在于,它们的函数体中不包含return语句,而是使用yield语句返回一个系列的元素。

>>> def letters_generator():
        current = 'a'
        while current <= 'd':
            yield current
            current = chr(ord(current)+1)
>>> for letter in letters_generator():
        print(letter)
a
b
c
d

当触发yield语句时,它会暂停并返回yield后的值,但不会破坏新生成的环境。当__next__再次被调用时,函数从原来位置上继续执行。

>>> letters = letters_generator()
>>> type(letters)
<class 'generator'>
>>> letters.__next__()
'a'
>>> letters.__next__()
'b'
>>> letters.__next__()
'c'
>>> letters.__next__()
'd'
>>> letters.__next__()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration

于是我们可以自定义迭代接口(Iterator Interface):

>>> class Letters:
        def __init__(self, start='a', end='e'):
            self.start = start
            self.end = end
        def __iter__(self):
            return LetterIter(self.start, self.end)
class LetterIter:
        """An iterator over letters of the alphabet in ASCII order."""
        def __init__(self, start='a', end='e'):
            self.next_letter = start
            self.end = end
        def __next__(self):
            if self.next_letter == self.end:
                raise StopIteration
            letter = self.next_letter
            self.next_letter = chr(ord(letter)+1)
            return letter  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值