HeLei Blog

迭代器&生成器&装饰器

迭代器

迭代器是访问集合元素的一种方式。迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束。迭代器只能往前不会后退迭代器的一大优点是不要求事先准备好整个迭代过程中所有的元素。迭代器仅仅在迭代到某个元素时才计算该元素,而在这之前或之后,元素可以不存在或者被销毁。这个特点使得它特别适合用于遍历一些巨大的或是无限的集合

特点:

  1. 访问者不需要关心迭代器内部的结构,仅需通过next()方法不断去取下一个内容
  2. 不能随机访问集合中的某个值 ,只能从头到尾依次访问
  3. 访问到一半时不能往回退
  4. 便于循环比较大的数据集合,节省内存

第一种方式,

1
2
3
list=["hello","world","china"]
for i in list:
print i

也是通常我们使用的遍历方式

第二种方式,

1
2
3
4
5
6
7
8
>>> list=["hello","world","china"]
>>> it=iter(list)
>>> while True:
try:
m=next(it)
print(m)
except StopIteration:
break

列表推导

1
2
3
4
5
>>> L = [x * x for x in range(10)]
>>> L
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
>>> type(L)
<type 'list'>

range(10)返回的也是一个list

生成器

通过列表生成式,我们可以直接创建一个列表。但是,受到内存限制,列表容量肯定是有限的。而且,创建一个包含100万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,那后面绝大多数元素占用的空间都白白浪费了。

所以,如果列表元素可以按照某种算法推算出来,那我们是否可以在循环的过程中不断推算出后续的元素呢?这样就不必创建完整的list,从而节省大量的空间。在Python中,这种一边循环一边计算的机制,称为生成器:generator。

一个函数调用时返回一个迭代器,那这个函数就叫做生成器(generator),如果函数中包含yield语法,那这个函数就会变成生成器。这个yield的主要效果呢,就是可以使函数中断,并保存中断状态,中断后,代码可以继续往下执行,过一段时间还可以再重新调用这个函数,从上次yield的下一句开始执行。

  • 用法一

    1
    2
    3
    >>> g = (x * x for x in range(10))
    >>> g
    <generator object <genexpr> at 0x1022ef630>
  • 用法二

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    def fab(n):
    a = 0
    b = 1
    while a <= n:
    yield a
    a, b = a+b, a
    for i in fab(5):
    print i
    0
    1
    1
    2
    3
    5

xrange是一个生成器,而range是迭代器。

装饰器

不希望修改变原有函数定义,在代码运行期间动态增加功能的方式,称之为“装饰器”(Decorator,类似于设计模式中的装饰器模式。

代码示例

1
2
3
4
5
6
7
8
9
10
11
12
def log(func):
def inner(*args, **kwargs):
print("__func__ = %s", func.__name__)
return func(*args, **kwargs)
return inner
@log
def now():
print "2018/03/22"
('__func__ = %s', 'now')
2018/03/22

坚持原创技术分享,您的支持将鼓励我继续创作!