可迭代对象以及列表生成式

可迭代对象

Python中,可以直接作用于for循环的对象统称为可迭代对象(Iterable)。包括:

  • 列表(list): [1, 2, 3]
  • 集合(set): {1, 2, 3}
  • 元组(tuple): (1, 2, 3)
  • 字符串(str): "123"
  • 生成器(generator): xrange(1, 4)

可以使用 isinstance() 方法判断一个对象是否是Iterable对象。

>>> from collections import Iterable
>>> isinstance([1, 2, 3], Iterable)
True
>>> isinstance({1, 2, 3}, Iterable)
True
>>> isinstance((1, 2, 3), Iterable)
True
>>> isinstance("123", Iterable)
True
>>> isinstance(xrange(1, 4), Iterable)
True

Python生成器与列表的区别。如果列表中有10000个对象,那么在构造这个列表的时候就需要占用10000个对象的内存,而生成器就不会占用这么多内存。generator保存的是算法,真正需要获取值的时候才会去计算下一个值,属于惰性计算(lazy evaluation)。

最简单的例子如内置函数 range(1, 10)xrange(1, 10),前者生成一个1到9的列表,后者生成一个1到9的生成器。

创建 generator

在Python中创建generator有两种方式

使用 Generator Function

通过关键词yield将函数变成 generator function

def get_generator():
    for i in range(1, 10):
        yield i

generator = get_generator()

函数执行到yield时就会停住,当需要下一个值时,会在yield的下一行继续执行。所以生成器函数即便是无限循环也没有问题。

例如利用yield生成斐波那契数列

def fibonacci():
    a, b = 0, 1
    while True:
        # 第一次next()函数执行到此返回a的值,然后停止运行。第二次执行next()时在这行代码的下一行继续执行。
        yield a
        # 先将 = 右面的值计算出来,然后分别复制给 = 左面的变量
        a, b = b, a + b

# 获取生成器
f = fibonacci()
print next(f),next(f),next(f),next(f),next(f),next(f),next(f),next(f)
# 0, 1, 1, 2, 3, 5, 8, 13

通过 () 与 嵌套 for 循环 构造 generator 生成器

注意: ()并不是要生成元组,而是生成generator生成器

lists = [[1, 2], [3, 4, 5], [6, 7, 8]]
# 生成 1 - 8 的生成器
generator = (x for list in lists for x in list)
# 生成 1 - 8 中为偶数的生成器
generator = (x for list in lists for x in list if x % 2 == 0)

引申:通过 for 循环构造集合

通过 for 循环生成list列表(列表生成式)

# 生成 2,4,6,8
list = [x * 2 for x in xrange(1, 5)]

通过 for 循环生成dict字典

# 键值是键的2倍
dict = {x : x * 2 for x in xrange(1, 5)}

通过 for 循环生成set集合

# set([1, 2, 3, 4]) 等价于 {1, 2, 3, 4}
set = {x for x in xrange(1, 5)}

注: 另外,dict 是 unhashable type: 'dict' 所以不可以将list dict转换成set dict,即不会存在set dict这种东西。如果想将list dict进行去重操作,可以使用下面的方法:

list_dict = [
               {
                   "date": "2017-9-30",
                   "status": "2"
               },
               {
                   "date": "2017-10-1",
                   "status": "1"
               },
               {
                   "date": "2017-10-1",
                   "status": "1"
               }
           ]
           
def deduplicate_list_dict(list_dict) = 
    deduplicate_set = set()
    for dict in list_dict:
        if dict['date'] not in deduplicate_set:
            yield dict
            deduplicate_set.add(dict['date'])

迭代器 Iterator

可以使用next()函数不断取值的对象就是Iterator对象。显然Iterable对象中,只有generator是Iterator。可以使用iter()函数将list、tuple、dict、set转换成Iterator。

>>> from collections import Iterator
>>> isinstance(iter([]),Iterator)
True

打赏一个呗

取消

感谢您的支持,我会继续努力的!

扫码支持
扫码支持
扫码打赏,一毛也是爱

打开支付宝扫一扫,即可进行扫码打赏哦