Python中的迭代器与生成器

一、推导式

推导式的引入提供了更加高效的方法来生成序列,并且没有失去代码的可读性。

1.列表推导式

格式:[ 返回值 循环体 条件 ]

注意:可以没有条件;列表推导式的输出为列表

例1:将字符串中的每个字母大写输出

str1 = "abcdefg"
list1 = [x.upper() for x in str1]
print(list1)

例2:打印50以内能被3整除的数的平方

list2 = [x ** 2 for x in range(1, 50) if x % 3 == 0]
print(list2)

2.集合推导式

格式:{ 返回值 循环体 条件 }

注意:跟列表推导式类似,但集合推导式使用大括号;集合推导式返回结果为集合,所以返回的结果自带去重

例1:输出列表lst中每个数的绝对值

lst = [-1, 1, 2, -2, 4, -5]
s1 = {abs(x) for x in lst}
print(s1)

代码运行结果:

3.字典推导式

格式:{ key:value 循环体 条件 }

注意:字典推导式返回的结果为字典

例1:将字典中的key与value值对调

d1 = {"a": 1, "b": 2}
d2 = {v: k for k, v in d1.items()}
print(d2)

例2:合并大小写对应的value值,将key统一写成小写

d = {'B': 3, 'a': 1, 'b': 6, 'A': 4}
result = {x.lower(): d.get(x.lower(), 0) + d.get(x.upper(), 0) for x in d}
print(result)

运行结果:

二、迭代器

可迭代对象:存储了元素的一个容器对象,实现了__iter__魔术方法。

迭代器对象:实现了__iter__和__next__魔术方法的对象称为迭代器对象。

其中,__iter__方法返回自身(迭代器对象);__next__方法返回下一个值。

如:

str1 = "abc"
iterator_str1 = str1.__iter__()
print(iterator_str1.__next__())
print(iterator_str1.__next__())
print(iterator_str1.__next__())

运行结果:

for语法糖

for先调用可迭代对象的__iter__方法,该方法返回一个迭代器

再对迭代器对象调用__next__方法,不断获取下一个值

直到获取完成抛出StopIteration异常退出

迭代器的优点:懒加载,惰性求值,需要的时候生成,可以节省空间

例:使用迭代器实现阶乘

class factorial():
    def __init__(self, stop, num=1, count=1):
        self.num = num
        self.stop = stop
        self.count = count
    
    def __iter__(self):
        return self

    def __next__(self):
        if self.count > self.stop:
            raise StopIteration
        self.num = self.num * self.count
        self.count +=1
        return self.num

f = factorial(5)
for i in f:
    print(i)

运行结果:输出1-5的阶乘

三、生成器

生成器是迭代器更加优雅的写法,不需要手动实现__iter__和__next__方法。生成器可以用更少的代码来实现迭代器的效果,相比于容器类型更加节省内存。

生成器有两种写法:一种叫生成器表达式,另一种叫生成器函数。

1.生成器表达式-类似于列表推导式

#求1-20之间能被3整除的数的平方
result = (x ** 2 for x in range(1, 21) if x % 3 == 0)
#生成一个生成器对象
print(result)
for i in result:
    print(i)

运行结果:

2.生成器函数

包含了yield关键字的函数就叫做生成器函数。yield关键字返回yield关键字后面的内容,保留中间算法,下次继续执行

例:

def get_content():
    print("first next".center(30, "*"))
    x = 2
    yield x
    print("second next".center(30, "*"))
    y = 3
    yield y
    print("third next".center(30, "*"))
    z = 4
    yield z

#类型实例化 g是一个生成器
g = get_content()
print(next(g))    #第一次执行next时,遇到yield就退出,返回yield后面携带的参数,还会记录当前执行的位置
print(next(g))    #第二次执行的时候就会从上一次执行的地方继续执行
print(next(g))

运行结果:

3.应用场景

生成器可以暂时挂起函数,并且保留函数的局部变量等数据,然后在再次调用它的时候,从上次暂停的位置继续执行下去。

(1)大文件处理

一次性读取大文件到内存太占空间,一行一行读效率太慢,可以使用生成器读取固定的字节的数据

#传入文件路径
def read_file(fpath):
    #指定一次性读文件的字节数
    BLOCK_SIZE = 1024
    with open(fpath, 'rb') as f:
        while True:
            block = f.read(BLOCK_SIZE)
            if block:
                yield block
            else:
                return
(2)send向生成器发送值

修改生成器的行为

def send_val():
    count = 0
    while 1:
        val = yield count
        if val is not None:
            count = val
        else:
            count += 1

s1 = send_val()
print(next(s1))
print(next(s1))
#使得生成器又从0开始计数
print(s1.send(0))
print(next(s1))

运行结果:

yield与yield from的区别:

def generator1():
    #yield后面必须接可迭代对象
    yield range(5)

def generator2():
    yield from range(5)
    #相当于:
    #for i in range(5)
    #    yield i

g1 = generator1()
g2 = generator2()

for i in g1:
    print(i)
for i in g2:
    print(i)

运行结果:

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值