第七章 Python系统模块 02-可迭代类型

可迭代类型

1. 可迭代对象与迭代器对象

collections包下的abc模块中,有一个Iterable,表示可迭代类型。可迭代类型即可以依次获取到每一个元素,可以使用for-in遍历。

from collections.abc import Iterable

print(isinstance(10, Iterable))  # False
print(isinstance('abc', Iterable))  # True
print(isinstance([], Iterable))  # True
print(isinstance(map(str, [10, 20, 30]), Iterable))  # True

在遍历可迭代类型的时候,有些是使用别的序列在记录遍历位置,有些则是自己在记录遍历位置。那么,记录着迭代位置的对象,就是一个“迭代器”。

from collections.abc import Iterator

print(isinstance(10, Iterator))  # False
print(isinstance('abc', Iterator))  # False
print(isinstance([], Iterator))  # False
print(isinstance(map(str, [10, 20, 30]), Iterator))  # True
'''
迭代器序列的数据的特点:
	取值只能向前 不能向后  取出之后 迭代器中就没有这个数据了
除了可以使用for-in进行遍历之外 还可以使用next(序列)获取序列中的元素
'''
s = 'hello'
for ch in s:
	print(ch)

print('===')

for ch in s:
	print(ch)
print('===')
'''
可迭代类型 非迭代器序列类型的数据 在遍历的时候 先创建一个迭代器对象 用它来记录位置 逐个获取元素
'''

# 迭代器序列类型的数据 先把自身设置迭代器【记录自身位置】 然后逐个取值
seq = map(str, [10, 20, 30])
for ele in seq:
	print(ele)
print('====')
for ele in seq:
	print(ele)

2. 自定义迭代器

在一个类中定义了 _iter_ 魔术方法的,就可以称为是可迭代对象了。这个方法需要返回一个迭代器对象,可以是自己,也可以是其他对象。

在一个类中同时定义了 _iter_ 和 __next__ 魔术方法的,就可以称为是迭代器对象了。

在使用for-in遍历可迭代对象的时候,其实是先获取到迭代器对象,然后每一次循环都调用__next__方法,获取到下一个元素。

class Fibonacci:
    def __init__(self, bound):
        self.bound = bound      # 记录边界
        # 记录从几开始遍历
        self.current = 1
        # 记录前两位的数字
        self.number_1 = 1
        self.number_2 = 1
        # 记录当前的数字
        self.current_number = 1

    def __iter__(self):
        return self

    def __next__(self):
        if self.current <= self.bound:
            if self.current > 2:
                self.current_number = self.number_1 + self.number_2
                # 为下一位做准备
                self.number_1 = self.number_2
                self.number_2 = self.current_number
            # 位数+1
            self.current += 1
            return self.current_number
        else:
            # raise ValueError("后面没有了")
            raise StopIteration


fib = Fibonacci(10)

for ele in fib:
    print(ele)

for ele in fib:
    print(ele)

print(isinstance(fib, Iterable))
print(isinstance(fib, Iterator))

自定义迭代器遍历其他序列

class MySequenceIterator:
    def __init__(self, seq):
        self.seq = seq      # 记录需要遍历的序列
        self.current = 0    # 记录当前遍历到的位置

    def __iter__(self):
        return self         # 以自己作为迭代器

    def __next__(self):
        if self.current < len(self.seq):
            # 获取到指定位的元素
            value = self.seq[self.current]
            # 迭代位置自增
            self.current += 1
            # 返回处理之后的数据
            return str(value).title()
        else:
            raise StopIteration


# 创建一个序列
l = ["hello world", "python language", "hadoop distributed file system", "mysql database"]
for e in MySequenceIterator(l):
    print(e)

3. 生成器

生成器是一种特殊的迭代器,支持迭代器的所有的操作。使用生成器主要用来生成一个序列的。

生成器分为两种:

  • 简单表达式:类似于列表推导式
  • 函数生成器:定义一个函数,用来生成一系列的数据,将return换成yield即可

简单表达式

# 列表推导式,直接生成一个列表
l1 = [f"{x:03d}" for x in range(1, 200) if x % 7 == 0 and x % 3 == 0]
print(l1)

# 简单表达式生成器,获取到一个生成器对象
l2 = (f"{x:03d}" for x in range(1, 200) if x % 7 == 0 and x % 3 == 0)
print(l2)       # <generator object <genexpr> at 0x10474b780>

print(next(l2)) # 021
print(next(l2)) # 042

函数生成器

def get_generator():
    for i in range(5, 10000, 5):
        if i % 3 == 0:
            yield i

"""
return: 结束函数,并把结果返回到调用的位置
yield: 根据逻辑,将数据产出并暂停生产。当下一次获取数据的时候,继续生产数据
"""
gen = get_generator()

print(next(gen))
print(next(gen))

生成器特点

生成器并不直接生成全部的数据,而是根据数据生成的逻辑,每次调用next的时候,才会生成一个元素

因此,生成器常用于在程序中使用大量的数据的时候,此时会有明显的内存占用的效果

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值