【从菜鸟到高手】 熟练使用 python 的 list,iterator,generator

版权声明:欢迎转载 https://blog.csdn.net/antony1776/article/details/84318658


请参考:
https://docs.python.org/3.6/tutorial/index.html
https://docs.python.org/3.6/reference/

在这里插入图片描述
Iterable,Iterator,Generator,list 之间的关系

1 list

尽量使用 python 的列表推导特性。

list(range(5)) 
# [0, 1, 2, 3, 4]

[i for i in range(10) if i % 2 == 0] 
# [0, 2, 4, 6, 8]

['%d:%s' % (i, v) for i, v in enumerate(['one', 'two', 'three'])] 
# ['0:one', '1:two', '2:three']

knights = {'gallahad': 'the pure', 'robin': 'the brave'}
["%s: %s" % (k,v) for k,v in knights.items()]
# ['gallahad: the pure', 'robin: the brave']

["%s: %s" % (k,v) for k,v in zip([1,2,3], ["one", "two", "three"])]
# ['1: one', '2: two', '3: three']
  • enumerate 产生一个能返回(索引,值)的迭代器!
  • zip 能将两个 list 中的值组合成一个 pair

2 Iterator

在 Python 中,可以直接进行 for 循环的数据类型有以下几种:

  1. list, tuple, dict, set, str
  2. generator, 包括生成器和带 yield 的 generator function

这些对象都统称为可迭代对象:Iterable
Iterable 对象不一定是迭代器 Iterator,因为迭代器不但可以进行 for 循环,还可以被 next() 函数调用并返回下一个迭代值,直到抛出 StopIteration 异常。

from collections import Iterable, Iterator
isinstance('abc', Iterable) # True
isinstance('abc', Iterator) # False

可以通过 iter 内建函数将 Iterable 对象转变为 Iterator

i = iter('123')
isinstance(i, Iterator) # True
next(i)    # 1
next(i)    # 2
next(i)    # 3
next(i)    # 产生 StopIteration 异常

自定义 Iterator 方法 1: 通过编写一个具有next方法的类

class MyIter(object):
    def __init__(self, num):
        self.num = num
    
    def __next__(self):
        if self.num == 0:
            raise StopIteration
        self.num -= 1
        return self.num

    def __iter__(self):
        return self

[i for i in MyIter(4)] # [3, 2, 1, 0]

自定义 Iterator 方法 2: 使用生成器

def myiter(num):
    while num > 0:
        num -= 1
        yield num

[i for i in myiter(4)] # [3, 2, 1, 0]

通过 next() 访问 Iterator 太麻烦了,一般通过 for … in 的形式来遍历它。

# next
try:
	while True:
		value = next(gen)
		process(value)
except StopIteration:
	break

# for ... in
for value in gen:
	process(value)

3 Generator

生成器可以更简洁、有效的生成迭代器。

通过 () 创建生成器

a = (i*i for i in range(4)) 
type(a) # generator object
next(a) # 0
next(a) # 1
next(a) # 4
next(a) # 9
next(a) # StopIteration

通过 yield 创建生成器:

def foo():
	yield 3

a = foo()
type(a) # generator

# 斐波拉切数列
def fib(max):
    n, a, b = 0, 0, 1
    while n < max:
        yield b
        a, b = b, a+b
        n += 1
    
    return 'done'

[i for i in fib(5)] # [1,1,2,3,5]

除了通过 next 方法实现迭代器,还可以通过 send 方法来获取输入。

def mg():
    print("first line")
    while True:
        vin = yield
        print("loop %s "% vin)

m = mg()
m.send(None)    # first line : start generator
m.send("1")     # loop 1
m.send("2")     # loop 2

a = mg()
next(a)     
a.send(2)       # loop 2

send 可以看做能够传参的 next

def demo(num):
    print("Start")
    while num > 0:
        vin = yield num
        print("loop: %s" % vin)
        num -= 1

d = demo(3)
r = d.send(None)    # r == 3
r = d.send(4)       # r == 2, loop: 4

可以得出以下关系:

yin = yield yout
sout = x.send(sin)
yin == sin      # True
yout == sout    # True

猜你喜欢

转载自blog.csdn.net/antony1776/article/details/84318658