【Python语法】可迭代对象、迭代器对象、迭代器、生成器:从傻傻分不清楚到清清楚楚

1. 可迭代对象

可以转换为不依赖索引取值的容器,通过__ iter __()方法生成迭代器对象

列表、字典、集合、字符串、元组,这类容器都是可迭代对象

2. 迭代器对象

迭代器对象也是可迭代对象,也有__ iter __ ()方法,会返回迭代器对象自身
可以通过__ next __() 方法进行取值

# 定义不同的容器,他们都是可迭代对象,也是迭代器对象
test_dict = {1: 'a', 2: 'b', 3: 'd'}
test_list = [100, 200, 300, 400]
test_set = {21, 22, 23, 24}

# 可迭代对象,通过__iter__()方法获得对应的迭代器对象
# 迭代器对象,使用__iter__()方法返回自身
iter_list = test_list.__iter__()
iter_dict = test_dict.__iter__()
iter_set = test_set.__iter__()

print(iter_list)
print(iter_dict)
print(iter_set)
print()
# 可迭代对象调用__iter__()方法,会返回自身
print(iter_list.__iter__())
print(iter_dict.__iter__())
print(iter_set.__iter__())

执行结果:

<list_iterator object at 0x0000025BA6C1E9C8>
<dict_keyiterator object at 0x0000025BA6B55BD8>
<set_iterator object at 0x0000025BA6C143B8>

<list_iterator object at 0x0000025BA6C1E9C8>
<dict_keyiterator object at 0x0000025BA6B55BD8>
<set_iterator object at 0x0000025BA6C143B8>

迭代器对象没有长度,不能使用len()函数

test_dict = {1: 'a', 2: 'b', 3: 'd'}
test_list = [100, 200, 300, 400]
test_set = {21, 22, 23, 24}

# 迭代器对象取值:
# 1. 顺序:按照名称空间的顺序取值
# 2. 容器:取一个少一个'''
print('list:%d' % iter_list.__next__())
print('dict:%d' % iter_dict.__next__())
# set没有取值顺序
print('set:%d' % iter_set.__next__())

new_list = iter_list.__iter__()
print('list:%d' % new_list.__next__())
# 字典的__next__()方法取到的是key
new_dict = iter_dict.__iter__()
print('dict:%d' % new_dict.__next__())
new_set = iter_set.__iter__()
print('set:%d ' % new_set.__next__())

执行结果:

list:100 dict:1 set:24
list:200 dict:2 set:21

迭代器对象取值没有尽头,在迭代器对象中没有元素时,会抛出StopIteration异常

while True:
    try:
        print(iter_list.__next__())
    except StopIteration:
        break

常见的迭代器对象有:enumerate()、file、生成器对象

3. 迭代器

即for循环,是用来从可迭代对象或迭代器对象中取值的方法

通过对象.__ iter ()方法获取容器对象的迭代器对象,在将_ next __() 方法获得的值赋值给 变量

当迭代器对象取完了,内部自动捕获异常,并结束循环

# 这里可以省略掉对象.__iter__()的写法,for语句内部已经对可迭代对象执行了__iter__()
for i in test_set.__iter__():
 print('iterator item: ', i)
with open('test','r',encoding='utf-8') as test_file:
    print(test_file)
    print(test_file.__next__())

4. 生成器

可以自定义的迭代器

生成器对象也是迭代器对象,因此可以通过__ next __()方法或者for语句迭代访问元素

# 迭代器方法中不用return,可多次使用yield依次返回值
def fn():
    print('step1')
    yield 1000
    print('step2')
    yield 2000

# 生成器对象也是迭代器对象,因此可以通过__next__()方法访问
f = fn()
print(f)
print(f.__next__())
print(f.__next__())
# for循环语句访问对生成器对象
for i in fn():
    print(i)

执行结果:

<generator object fn at 0x000001C1E0A8ECC8>
step1
1000
step2
2000
step1
1000
step2
2000

生成器方法可以传入参数,可以传入可变参数,对任意长度的参数迭代返回结果

# 定义生成器,对传入参数double返回
def fn1(*args):
    i = 0
    # 可变参数args是一个容器
    while i < len(args):
        yield args[i] * 2
        i += 1


for i in fn1(1, 23, 42, 142):
    print(i)

执行结果:

2,46,84,284,

注意观察生成器中的yield语句,每次迭代,生成器会返回yield语句的结果,之后从yield语句处继续下一次迭代

# 定义生成器,可以无限生成自然数的阶乘
def fn2():
    total = 1
    count = 1
    while True:
        total *= count
        # 每次遇到yield语句就返回,但是后面的语句会接着执行
        yield total
        count += 1


f2 = fn2()
print(f2.__next__())
print(f2.__next__())
print(f2.__next__())
print(f2.__next__())

执行结果:

1
2
6
24

生成器对象的send方法配合yield语句使用:

a) 为当前停止的yield传入参数,供下一次逻辑使用

b) 自身也会调用__ next __()获取下一个yield的结果

def fn3():
    msg = yield 501
    print(msg)
    yield 502
    yield 503


f3 = fn3()
print(f3.__next__())
# 默认的send参数是None,注意不能在生成器第一次返回的时候send方法,因为此时生成器还没有走到任何yield语句
res = f3.send('send me')
print(res)
print(f3.__next__())

执行结果:

501
send me
502
503

# 生成器对象的send方法示例
def fn4(namelist):
    count = 0
    print('%s在面试' % namelist[count])
    while count < len(namelist):
        name = yield namelist[count]
        count += 1
        print(name + '叫%s来面试' % namelist[count])


name_list = ['Amy', 'Bob', 'Christain', 'David']
f4 = fn4(name_list)
name = f4.send(None)
print(name + '面试完毕')

while True:
    try:
        name = f4.send(name)
        print(name + '面试完毕')
    except Exception:
        print('所有人面试完毕')
        break

执行结果:

Amy在面试
Amy面试完毕
Amy叫Bob来面试
Bob面试完毕
Bob叫Christain来面试
Christain面试完毕
Christain叫David来面试
David面试完毕
所有人面试完毕

课后小练:

# 自定义一个range
class myrange():
    def __init__(self, start, end):
        self.start = start
        self.end = end

    # range是迭代器,所以要定义__iter__方法。并返回自身
    def __iter__(self):
        return self

    # 定义迭代器的__next__方法
    def __next__(self):
        if self.start < self.end:
            self.start += 1
            return self.start - 1
        else:
            raise StopIteration


for i in myrange(1, 3):
    print(i)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值