5 Python学习记录- 可迭代对象

1 迭代器与可以迭代对象

python中可以循环的字符串、容器都是可迭代对象。了解迭代必须要明白两个内置函数iter()和next()

1.1 iter()和next() 内置函数

iter() 返回一个迭代器对象;

print(iter([1,2,3]))

print(iter("hello"))

print(iter(123))
# 输出
<list_iterator object at 0x10a979d60>
<str_iterator object at 0x10a979d60>
Traceback (most recent call last):
TypeError: 'int' object is not iterable

迭代器(interator): 迭代器帮助迭代的对象,特点是可以通过next(),不断获取迭代器中下一个成员,如果没有更多的值返回抛出StopInteration异常。

l = [1, 2, 4, "x"]
i = iter(l)
print(i)  # <list_iterator object at 0x10324ae80>
print(next(i))  # 1
print(next(i))  # 2

i_1 = iter(i)

print(i is i_1) # True

python循环都是先通过iter(obj), 获得迭代器,然后通过next() 获取迭代器中的值。

2、自定义迭代器

自定义迭代器需要实现 

1 __iter__: 调用的时候返回迭代器本身。 
2 __next__: 调用next()的时候触发,通过returen返回结果。如果没有更多的内容就抛出异常。
class Range7:
    """生成某个范围内被7整除或包含7的整数"""

    def __init__(self, start, end):
        self.start = start
        self.end = end
        self.current = start

    def __iter__(self):
        return self

    def __next__(self):
        while True:
            if self.current >= self.end:
                raise StopIteration
            if self.num_is_valid(self.current):
                ret = self.current
                self.current += 1
                return ret
            self.current += 1

    def num_is_valid(self, num):
        if num == 0:
            return False
        return num % 7 == 0 or '7' in str(num)

测试代码:

r = Range7(0, 20)
print(r)
for num in r:
    print(num)

# 第二次遍历拿不到任何数据
for num in r:
    print(num)

第二次不反回结果是因为self.current 没有被重置,是因为所有的迭代器,都是这样设计的。

3、区分迭代器与可迭代对象

迭代器有时候与可迭代对象非常相似,但是其含义不相同:

迭代器:迭代器是可迭代对象的一种,在迭代其他对象时,迭代器作为一种介质或者工具对象的存在,迭代的list或者字符串的时候返回list_interator或str_interator等。每次迭代器迭代一个可迭代对象都要保证迭代的顺序从最顶开始。

迭代器必须同时实现两个魔法方法:1 __iter__ 、  2 __next__:

可迭代对象:可迭代对象,判断一个对象是不是可迭代对象,通过iter(obj), 看返回结果是不是一个迭代器,因为可迭代对象只需要实现 __iter__ 方法, 不一定要实现 __next__ 方法。

为了让Range7对象每次迭代都返回结果:需要自定义可迭代对象Rang7和 自定义迭代器Range7Interator

class Range7:
    """生成某个范围内被7整除或包含7的整数"""

    def __init__(self, start, end):
        self.start = start
        self.end = end

    def __iter__(self):
        return Range7Interator(self)


class Range7Interator:

    def __init__(self, range7_obj):
        self.range7_obj = range7_obj
        self.current = range7_obj.start

    def __iter__(self):
        return self

    def __next__(self):
        while True:
            if self.current >= self.range7_obj.end:
                raise StopIteration
            if self.num_is_valid(self.current):
                ret = self.current
                self.current += 1
                return ret
            self.current += 1

    def num_is_valid(self, num):
        if num == 0:
            return False
        return num % 7 == 0 or '7' in str(num)

测试代码:

r = Range7(0, 20)
print(r)
for num in r:
    print(num)

# 第二次遍历:仍然可以拿到数据
for num in r:
    print(num)

总结一下迭代器与可迭代对象的区别:

1、可迭代对象不一定是迭代器,迭代器一定是可迭代对象。

2、可迭代对象使用iter()会返回迭代器,迭代器调用iter() 返回迭代器自身

3、每个迭代器的被迭代过程是一次性的,可迭代对象则不一定。

4、可迭代对象只需要实现_ _ iter_ _ 方法,而迭代器需要额外实现 _ _ next _ _ 方法。

2  生成器是迭代器

2.1生成器是一种简化了的迭代器的实现

 可以使用生成器来降低传统迭代器的编码成本,不需要实现两个方法来实现迭代器。

class Range7:
    """生成某个范围内被7整除或包含7的整数"""

    def __init__(self, start, end):
        self.start = start
        self.end = end

    def __iter__(self):
        return self.range_generator(self.start, self.end)

    def range_generator(self, start, end):
        num = start
        while num < end:
            if num != 0 and (num % 7 == 0 or '7' in str(num)):
                yield num
            num += 1

测试代码:

range_ = Range7(0, 20)
for x in range_:
    print(x)

for x in range_:
    print(x)

同构定义一个生成器函数,同样实现了Range7是一个可迭代对象。  

2.2 生成器函数修饰可迭代对象

生成器函数 修饰可迭代对象,类似于filter, 可以过滤可迭代对象

def sum_only(numbers):
    """对numbers的偶数求和
    """
    result = 0
    for num in numbers:
        if num % 2 == 0:
            result += num
    return result

定义生成器修饰numbers类似于过滤:

def even_only(numbers):
    for num in numbers:
        if num % 2 == 0:
            yield num


def sum_only_v1(numbers):
    """对numbers的偶数求和
    """
    result = 0
    for num in even_only(numbers):
        result += num
    return result

生成器优化写法:

def sum_only_v2(numbers):
    """对numbers的偶数求和
    """
    result = 0
    for num in [num for num in numbers if num % 2 == 0]:
        result += num
    return result

3 代码优化

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值