首页 > 其他分享 >23. 迭代器

23. 迭代器

时间:2024-10-26 18:43:18浏览次数:1  
标签:__ 迭代 23 self people iter print

一、什么是迭代器

  迭代器 指的是迭代取值的工具,迭代是一个重复的过程,每次重复都是基于上一次的结果而继续的,单纯的重复并不是重复。迭代器是用来迭代取值的工具,而涉及到把多个值循环取出的数据类型有:列表、字符串、元组、字典、集合、打开的文件对象等。

  我们可以通过 while 循环的方式取值,这种取值方式只适用于有索引的数据类型,如:列表、字符串、元组等。

names = ["Sakura","Mikoto","Shana"]

i = 0
while i < len(names):
    print(names[i])
    i += 1

  为了解决基于索引迭代器取值的局限性,Python 需要提供一种能够不依赖索引的取值方式,这就是迭代器。在 Python 中,但凡是内置有 __iter__() 方法的对象都称为 可迭代对象。在 Python 中,列表、字符串、元组、字典、集合、打开的文件对象等都内置了 __iter__() 方法。调用可迭代对象的 __iter__() 方法会将其转换成迭代器对象。转换为迭代器对象后,我们可以通过 __next__() 方法获取迭代器对象的下一个值。

names = ["Sakura", "Mikoto", "Shana"]

iterator = person.__iter__()
print(iterator)
print(type(iterator), end="\n\n")

while True:
    try:
        print(iterator.__next__())
    except StopIteration:
        break
names = ["Sakura", "Mikoto", "Shana"]

iterator = iter(names)
print(iterator)
print(type(iterator), end="\n\n")

while True:
    try:
        print(next(iterator))
    except StopIteration:
        break

如果我们迭代到最后一项,再调用 __next__() 方法或 next() 方法会抛出 StopIteration 异常;

  迭代器对象 是指内置有 __next__() 方法和 __iter__() 方法的对象。调用迭代器对象的 __next__() 方法将得到迭代器对象的下一个值。调用迭代器对象的 __iter__() 方法将得到迭代器的本身,与没调用该方法一样。

person = {"name":"Sakura","age":10}

iterator = iter(person)
print(iterator is  iterator.__iter__() is iterator.__iter__().__iter__())

  如果我们想判断某一个数据类型或对象是否可以迭代,我们可以使用 collections 模块来判断;

from collections.abc import Iterable, Iterator

data = "Sakura"
print("可迭代对象-字符串:", isinstance(data, Iterable))
print("迭代器-字符串:", isinstance(data, Iterator))
print()

data = ["Sakukra", "Mikoto", "Shana"]
print("可迭代对象-列表:", isinstance(data, Iterable))
print("迭代器-列表:", isinstance(data, Iterator))
print()

data = ("Sakukra", "Mikoto", "Shana")
print("可迭代对象-元组:", isinstance(data, Iterable))
print("迭代器-元组:", isinstance(data, Iterator))
print()

data = {"Sakukra", "Mikoto", "Shana"}
print("可迭代对象-集合:", isinstance(data, Iterable))
print("迭代器-集合:", isinstance(data, Iterator))
print()

data = {"name": "Sakura", "age": 10}
print("可迭代对象-字典:", isinstance(data, Iterable))
print("迭代器-字典:", isinstance(data, Iterator))
print()
from collections.abc import Iterable, Iterator

class People:
    def __init__(self):
        self.container = []
  
people = People()
print("可迭代对象:", isinstance(people, Iterable))
print("迭代器:", isinstance(people, Iterator))

二、自定义迭代器

  只要在类中定义 __iter__() 方法,那么这个类创建出来的对象一定是可迭代的。通俗的说:一个具备了 __iter__() 方法的对象,就是一个可迭代对象。

from collections.abc import Iterable, Iterator

class People:
    def __init__(self):
        self.container = []

    def __iter__(self):
        pass
  
people = People()
print(isinstance(people, Iterable))
print("迭代器:", isinstance(people, Iterator))

  如果想实现自定义迭代器的话,除了在类中定义 __iter__() 方法还需要在类中再定义 __next__() 方法,即一个实现了 __iter__() 方法和 __next__() 方法的对象,就是迭代器。

from collections.abc import Iterable, Iterator

class People:
    def __init__(self):
        self.container = []
  
    def add(self, name):
        self.container.append(name)

    def __iter__(self):
        # 这个方法有两个功能:
        # 1.标记用当前类创建出来的对象是一定是可迭代对下个你
        # 2.当调用iter()函数时,这个方法会被自动调用,返回的自己指定的那个迭代器
        return MyIterator(self)

class MyIterator:
    def __init__(self, obj):
        self.obj = obj
        self.current = 0

    def __iter__(self):
        pass

    def __next__(self):
        # 这个方法有两个功能:
        # 1.标记当前类创建的对象(一定有__iter__()方法)一定是迭代器
        # 2.当调用next()函数时,这个方法会自动调用,它返回一个数据
        if self.current < len(self.obj.container):
            item = self.obj.container[self.current]
            self.current += 1
            return item
        else:
            raise StopIteration
  
people = People()
print("People-可迭代对象:", isinstance(people, Iterable))
print("People-迭代器:", isinstance(people, Iterator))
print()

iterator = MyIterator(people)
print("MyIterator-可迭代对象:", isinstance(iterator, Iterable))
print("MyIterator-迭代器:", isinstance(iterator, Iterator))
print()

people.add("Sakura")
people.add("Mikoto")
people.add("Shana")

for item in people:
    print(item)

 for 循环是一个已经实现的功能,它里面自带了 iter()、next() 方法,并且带有 StopIteration 异常判断,通过这个异常判断来决定是否还需要获取迭代器对象。如果自己规定用 None 来表示数据获取完毕,但是 for 循环的代码依然用的是异常处理,所以 for 循环会产生死循环。

from collections.abc import Iterable, Iterator

class People:
    def __init__(self):
        self.container = []
        self.current = 0
  
    def add(self, name):
        self.container.append(name)

    def __iter__(self):
        # 这个方法有两个功能:
        # 1.标记用当前类创建出来的对象是一定是可迭代对下个你
        # 2.当调用iter()函数时,这个方法会被自动调用,返回的自己指定的那个迭代器
        return self
  
    def __next__(self):
        # 这个方法有两个功能:
        # 1.标记当前类创建的对象(一定有__iter__()方法)一定是迭代器
        # 2.当调用next()函数时,这个方法会自动调用,它返回一个数据
        if self.current < len(self.container):
            item = self.container[self.current]
            self.current += 1
            return item
        else:
            self.current = 0
            raise StopIteration

people = People()

people.add("Sakura")
people.add("Mikoto")
people.add("Shana")

for item in people:

当对一个可迭代对象调用 iter() 方法时,它会自动调用这个可迭代对象的 __iter__() 方法,这个方法返回的对象当做迭代器;

当对一个迭代器对象i调用 next() 方法时,它会自动调用这个迭代器对象的 __next__() 方法,这个方法返回想要的那个数据;

标签:__,迭代,23,self,people,iter,print
From: https://www.cnblogs.com/FlurryHeart/p/18504343

相关文章

  • RF/射频器件: CMD246C4 CMD235C4 CMD236C4 CMD254C3 CMD299K4 CMD262 一款5 W GaN MMI
    CMD246C4是一款宽带GaAsMMIC低相位噪声放大器,采用无引脚表贴封装,非常适合军事、航天和通信系统。16GHz时,该器件提供17dB的增益,饱和输出功率为+18dBm,噪声系数为5dB。此外,对于10GHz的输入信号,该放大器在10kHz失调下具有-165dBc/Hz的低相位噪声性能。CMD235C4是一款宽带MMI......
  • 2024.10.23
    Java连接mysql数据库1.1流程java连接mysql大致需要这六步:导入驱动包:这里我使用的是mysql-connector-java-8.0.17.jar(点击下载),这个包连接mysql5.6,5.7,8.0版本都没问题。Class.forName("com.mysql.cj.jdbc.Driver");url和账户名密码JDBC连接串:jdbc:mysql://<地址>:<端口>/<......
  • springboot二手物品交易平台-计算机毕业设计源码02234
    目 录摘要1绪论1.1研究背景及意义1.2国内外研究现状1.3论文结构与章节安排2系统分析2.1可行性分析2.1.1技术可行性分析2.1.2经济可行性分析2.1.3操作可行性分析2.2系统流程分析2.2.1数据流程3.3.2业务流程2.3功能分析2.3.1功能性分......
  • GESP一级真题分析-202303-选择题1-输入输出设备、存储单位、默认数据类型、标识符命名
    GESP一级真题分析-202303-选择题1-输入输出设备、存储单位、默认数据类型、标识符命名PDF文档公众号回复关键字:202410261相关知识点1)输入输出设备输入设备是外界向计算机传送信息的装置。在微型计算机系统中,最常用的输入设备是键盘和鼠标。此外还有电子光笔、数字化......
  • [CSP-J 2023] 一元二次方程(模拟)
    变态的大模拟……洛谷题目传送门https://www.luogu.com.cn/problem/P9750解题思路主要还是模拟,题目让你求啥你就求啥,要注意细节。然后化简根式的可以用质因数分解一下即可。代码#include<bits/stdc++.h>usingnamespacestd;#defineintlonglongintq,n;intaabs(......
  • LeetCode|3180. 执行操作可获得的最大总奖励 I(day23)
    作者:MJ昊博客:掘金、CSDN等公众号:程序猿的编程之路今天是昊的算法之路第23天,今天分享的是LeetCode第3180题执行操作可获得的最大总奖励I的解题思路。这是一道中等难度的题目,要求我们在给定的奖励值数组中,通过某些操作尽可能获取最大总奖励。题目描述简要回顾题目要......
  • The 2023 CCPC (Qinhuangdao) Onsite / The 2nd Universal Cup. Stage 9: Qinhuangdao
    B.YetAnotherSubsequenceProblem题意:按照给定方式生成01串,求本质不同子序列个数,生成方式可以理解为从\((0,0)\)沿折线走到\((A,B)\),若在折线上方或在折线上,就往右走(\(0\)),否则往上走(\(1\))。套路地设\(f_{i,0/1}\)前\(i\)个数以\(0/1\)结尾的不同子序列个数,显然可......
  • E71 树形DP+二分 P3523 [POI2011] DYN-Dynamite
    视频链接:   P3523[POI2011]DYN-Dynamite-洛谷|计算机科学教育新生态//树形DP+二分O(nlogn)#include<iostream>#include<cstring>#include<algorithm>usingnamespacestd;intread(){intx=0,f=1;charc=getchar();while(c>'9'||c......
  • 第九届中国大学生程序设计竞赛 深圳站(CCPC 2023 Shenzhen Site)/ The 2nd Universal Cu
    D.BotBrothers题意:有一棵\(n\)个点的树,\(m\)个叶子,编号为\(1\simm\)。两人在树上博弈,均从根出发,轮流行动,每次走向一个当前所在节点的子节点,如果在叶子就不移动。最终如果两人所在叶子编号一个是另一个\(+1\)(\(\pmodm\)意义下),则\(+1\)的一方获胜。观察到先手不可能......
  • CSP2023游寄
    没啥好说的,寄了。快来嘲讽这个pj130tg115的小丑罢。upd:pj挂成了105,这下tg比pj还高了,乐。在CSP2024的前夕,我想了想,还是决定把这个唐诗游记写出来。J8:30开考。看T1,马上往数学方面想,但是想了一会没想出来。这时旁边的小朋友已经开始测T2了,有点慌。强迫自......