我是靠谱客的博主 天真日记本,最近开发中收集的这篇文章主要介绍python的迭代器与生成器,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

首先理解下面的这边概念内容

1、可迭代对象:元素一开始就已经存在,比如常用的字符串,列表(list: [0, 1, 2]),元组(tuple: (0, 1, 2)),字典(dict: {0:0, 1:1, 2:2}),集合(set: set([0, 1, 2]))

2、迭代器:可迭代对象调用iter()方法返回的对象,就是一个迭代器,可以使用next()方法实现遍历,可以使用iter()函数判断是否是可迭代对象,比如下面的这些对象

def is_iterable(param):
    try:
        iter(param)
        return True
    except TypeError:
        return False

params = [
    12,
    "123",
    [1,2,3,"ad"],
    (3,3,21,"er"),
    {3,12,"ad","asd"},
    {1:"ad", 2:"er"}
]
for i in params:
    print(f"{i} is iterable? {is_iterable(i)}")

执行结果:

再来看可迭代对象是什么样的:

list = [i for i in range(3)]
print(f"list is {list}")
l_iter = iter(list)
print(f"l_iter is {l_iter}")
print(next(l_iter))
print(next(l_iter))
print(next(l_iter))
print(next(l_iter))

执行结果:

列表执行iter()函数返回一个迭代器对象list_iterator,执行next()函数可以实现遍历,因为列表的长度是3,超过列表的长度时,执行next()函数,会报StopIteration异常

3、生成器:可以理解成特殊的迭代器,元素只有调用next()函数的时候才会生成,在Python中是用小括号括起来的,比如(i for i in range(10))

gena = (j for j in range(3))
print(f"gena is {gena}")
print(next(gena))
print(next(gena))
print(next(gena))
print(next(gena))

运行结果:和list的结果一样,只不过生成器是执行next()函数的时候才生成的内容

4、然后我们来看看for循环对于迭代器的重要作用:

#迭代器
list = [i for i in range(3)]
print(f"list is {list}")
for it in list:
    print(f'this is list: {it}')
l_iter = iter(list)
print(f"l_iter is {l_iter}")
for it in l_iter:
    print(f"this is l_iter: {it}")

#生成器
gena = (j for j in range(3))
print(f"gena is {gena}")
for it in gena:
    print(f"this is gena: {it}")

执行结果:

也就是说,我们遍历迭代器的时候,不用每次都调用iter()和next(),for循环直接把这两个函数的操作隐视化了,很方便,还有一点值得注意的是,for循环可以遍历容器(list),也可以遍历迭代器和生成器,可能底层实现是根据对象的类型调用的不同的函数

5、yield对于生成器的作用

生成器不仅可以用括号生成,使用函数也可以创建生成器,yield就是其中的关键

#函数表示生成器,生成器验证数学中的一个恒等式
#(1 + 2 + 3 + ... + n)^2 = 1^3 + 2^3 + 3^3 + ... + n^3
def genaretor(k):
    print(f"this is genaretor{k}")
    i = 1
    while True:
        yield i ** k
        i += 1


gen1 = genaretor(1)
gen3 = genaretor(3)
print(gen1)
print(gen3)

def sum(n):
    sum1, sum2 = 0, 0
    for i in range(n):
       next1 = next(gen1)
       next2 = next(gen3)
       print(f"next1 is {next1}, next2 is {next2}")
       sum1 += next1
       sum2 += next2
    
    print(f"(1+2+3+4+...+n)^2 is {sum1 * sum1}, (1^3 + 2^3 + 3^3 +...+ n^3) is {sum2}")

sum(10)

执行结果:

首选,print打印的gen1,gen3都是一个生成器,如之前所说,我们可以用next()函数执行遍历,next1和next2的值就是next()调用生成器的结果

这里说明一下yield这个魔术,可以理解成第一次执行到yield的时候,跳出这个函数,yield 后面表达式的执行结果返回给next()函数,上面的函数就是赋值给next1

在sum()函数中,第一次执行next()函数的时候,进入生成器gen1,然后函数print,执行到yield 1**1的时候跳出这个函数,1**1返回给next()函数,赋值给next1,然后外层的for循环再次执行到next()函数的时候,暂停的程序又重新开始了,从yield往下执行,局部变量i还是暂停时的值,i可以一直累加,所以只要一直next(),生成器就可以一直生成值

6、生成器的骚操作

看下面的问题:判断一个序列是不是另一个序列的子序列,子序列则指的是,一个列表的元素在第二个列表中都按顺序出现,但是并不必挨在一起。

举个例子,[1, 3, 5] 是 [1, 2, 3, 4, 5] 的子序列,[1, 4, 3] 则不是。

如果不使用生成器,我们需要遍历第二个序列,找到第一个序列和第二个序列一样的值一样的时候,第一个序列的index前进一位,第一个index移出第一个序列最后一个元素的时候,返回 True,否则返回 False。

代码如下:

#不使用生成器
def is_subsequence(sub_list, up_list):
    sub_index = 0
    for i in up_list:
        if i == sub_list[sub_index]:
            sub_index += 1
            if sub_index > len(sub_list) - 1:
                break
    # 当sub的index遍历完sub_list的时候就是子序列
    if sub_index > len(sub_list) - 1:
        return True
    else:
        return False


print(is_subsequence([1,2,3], [1,4,2,3,5]))
print(is_subsequence([1,3,2], [1,4,2,3,5]))
print(is_subsequence([1,3,3], [1,4,2,5]))
print(is_subsequence([1,3,2,6,6], [1,3,2,6,5]))

执行结果:

如果是使用生成器的话,可以大大的减少代码行数

代码如下:

#使用生成器
def is_subsequence_genaretor(sub_list, up_list):
    # 生成一个迭代器
    up_iter = iter(up_list)
    # all里面的值全为true的时候返回true
    return all((i in up_iter) for i in sub_list)

print(is_subsequence_genaretor([1,2,3], [1,4,2,3,5]))
print(is_subsequence_genaretor([1,3,2], [1,4,2,3,5]))
print(is_subsequence_genaretor([1,3,3], [1,4,2,5]))
print(is_subsequence_genaretor([1,3,2,6,6], [1,3,2,6,5]))

结果如下:

其中令人难以理解的部分可能就是(i in up_iter)这个东西了,因为up_iter是一个迭代器,所以(i in up_iter)这部分代码,可以理解成下面这段代码:

while True:
    val = next(b)
    if val == i:
        yield True

我们来看看 in在迭代器和容器(set,list,dict等)里面使用的区别:

#容器里面的in
t_list = [1,3,4,2]
print(f"1 in t_list? {(1 in t_list)}")
print(f"2 in t_list? {(2 in t_list)}")
print(f"3 in t_list? {(3 in t_list)}")
print(f"4 in t_list? {(4 in t_list)}")
# 迭代器里面的in
i_list = iter(t_list)
print(f"1 in i_list? {(1 in i_list)}")
print(f"2 in i_list? {(2 in i_list)}")
print(f"3 in i_list? {(3 in i_list)}")
print(f"4 in i_list? {(4 in i_list)}")

执行结果:

可以看到,迭代器里面的in,是有执行next()这个操作的了

所以上面的(i in up_iter) for i in sub_list,相当于先遍历sub_list赋值给 i, 然后再往后遍历up_iter,判断i是否在up_iter里面,并且是next()执行一直往后,直到遍历到最后返回结果

最后

以上就是天真日记本为你收集整理的python的迭代器与生成器的全部内容,希望文章能够帮你解决python的迭代器与生成器所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(33)

评论列表共有 0 条评论

立即
投稿
返回
顶部