首页 > 编程语言 >Python - Creating your own Iterator

Python - Creating your own Iterator

时间:2024-07-31 10:27:59浏览次数:14  
标签:__ own Creating iterator Python self method source class

In our first example, we will create iterable objects, which, when iterated over, will give out cubes of numbers, and these objects will support multiple iterations.

class Cubes:
    def __init__(self, start, stop):
        self.start = start
        self.stop = stop

    def __iter__(self):
        return CubesIterator(self)


class CubesIterator:
    def __init__(self, source):
       self.source = source  
       self.current = source.start

    def __next__(self):
        if self.current > self.source.stop:
            raise StopIteration
        else:
            x = self.current
            self.current += 1
            return x * x * x


x = Cubes(2,8)
for i in x:
    print(i, end=' ')
print('Sum =',sum(x))

Output-

8 27 64 125 216 343 512 Sum = 1295

Let us understand the code for the class Cubes. The initializer method takes two arguments, and inside it, we have created two instance variables start and stop. The __iter__ method should return a fresh iterator object every time it is invoked. So, inside this method we create and return an instance of the class CubesIterator. Now, let us understand the code for the class CubesIterator.

The __init__ method has a parameter named source which will accept the iterable that has to be iterated over. In the __iter__ method of the Cubes class, when we create an instance of this CubesIterator class, we have sent self as an argument, which is the iterable that needs to be iterated over.

Inside the __init__ method, we have written self.source = source, so now this iterator class has access to all the instance variables of the object named source. Next we create an instance variable current that is set equal to source.start. Now, let us see the __next__ method.

If the current is greater than the stop of the source object, then a StopIteration exception will be raised. If it is not, then the cube of the current number will be returned, and the value of the current will be increased by 1. So, this class will create stateful iterator objects that store the current state. The state in this iterator is kept inside the instance variable current. When the method __next__ is called, it produces and returns the result for the current call and it also modifies the state for the next call. So, you can think of an iterator as a value factory; whenever you request the next value from it, it knows how to compute it because it holds the current internal state. It remembers its state between calls.

 

In our next example, we have created a class named Fibonacci which will create iterable objects that give out Fibonacci numbers up to a certain value. In Fibonacci series, each number is the sum of previous two numbers.

# Fibonacci series: 0 1 1 2 3 5 8 13 21 34 55 89

class Fibonacci:
    def __init__(self, max):
        self.max = max

    def __iter__(self):
        return FiboIterator(self)


class FiboIterator:
    def __init__(self, source):
        self.source = source
        self.a = 0
        self.b = 1

    def __next__(self):
        f = self.a
        if self.a > self.source.max:
            raise StopIteration
        self.a, self.b = self.b, self.a + self.b
        return f


x = Fibonacci(100)
for i in x:
    print(i, end=' ')
print(55 in x, 50 in x)

Output-

0 1 1 2 3 5 8 13 21 34 55 89 True False

We have created an instance object of class Fibonacci and used it in a for loop and in the in operator. The class Fibonacci has two methods __init__ and __iter__. The __init__ method takes an argument and creates an instance variable max which denotes the number up to which we want to generate the Fibonacci numbers. The __iter__ method returns an iterator object of the class FiboIterator. This is the class that maintains the state information.

In the __init__ method of FiboIterator, we have created three instance variables. source is the iterable that has to be iterated over. The state inside the iterator is maintained with the help of instance variables a and b. The instance variable a is initialized to 0 and b to 1.

The __next__ method is responsible for calculating and returning the next term of the series.

 

In the two examples that we have seen, we created two classes each: the iterable class and the iterator class. The iterator class needs to access the data members of the iterable class, and that is why the iterable class passes a reference of its current object to the initializer of the iterator class. Instead of passing reference to the object, you can simply pass the instance variable that will be needed by the iterator. For example, in FiboIterator you could pass self.max, and in CubesIterator, you could pass self.start and self.stop. It will also work, but it is better to pass the self object instead of passing individual instance variables. When you pass the source object, in the iterator you only have to create instance variables that are responsible for maintaining the state.

We saw two examples where we created objects that supported multiple active iterations. If we do not want our objects to support multiple iterations then the whole thing can be put inside a single class.

class Fibonacci:
    def __init__(self, max):
        self.max = max
        self.a = 0
        self.b = 1

    def __iter__(self):
        return self

    def __next__(self):
        f = self.a
        if f > self.max:
            raise StopIteration
        self.a, self.b = self.b, self.a + self.b
        return f


x = Fibonacci(100)
for i in x:
    print(i, end = ' ')
print(50 in x, 55 in x)

Output-

0 1 1 2 3 5 8 13 21 34 55 89 False False

In this program, we have only a single class, and its objects will support a single iteration.

The __iter__ method now returns self instead of returning a fresh iterator. The __next__ method is now written in this class itself instead of a separate class. The state-maintaining variables a and b are also a part of this class. Now, we do not need a separate iterator class; this class is its own iterator.

From the output, we can see that object x supports only a single iteration. The in operator did not work because after the for loop, the iterator was exhausted. When the in operator demanded an iterator, it got the same exhausted iterator because now the __iter__ method returns self instead of returning a fresh iterator.

This way, we can write a single class for both the iterator and the iterable. This type of class will create an iterator object that supports only a single iteration.

 

标签:__,own,Creating,iterator,Python,self,method,source,class
From: https://www.cnblogs.com/zhangzhihui/p/18334078

相关文章

  • 三种语言实现前缀和(C++/Python/Java)
    题目输入一个长度为n的整数序列。接下来再输入m个询问,每个询问输入一对l,r对于每个询问,输出原序列中从第l个数到第r个数的和。输入格式第一行包含两个整数n和m。第二行包含n个整数,表示整数数列。接下来m行,每行包含两个整数l和r,表示一个询问的区间范围。......
  • Python - 旨在通过命令提示符执行数据清理,但代码似乎无法运行
    我从一位同事那里收到了这段代码,我打算用它来处理100csv文件以提取有关粒子的值。代码如下所示:importsysimportcsv#Usage#skdata_decode.py[inputfile1][inputfile2]...#(Itispossibletousefiledcardtospecifyinputfiles.)##l......
  • 如何在 python 终端中的 x,y 位置上书写(基于文本)
    我想在python(基于文本)的终端中的定义位置(x,y)上写入字符。假设,我有一个大小为25x80的终端,并且想要在位置(2,20)上写入字符。我可以在Python中执行此操作吗?现在,我使用25x80数组,并写入该数组。为了在屏幕上显示,我清除屏幕并将该数组的全部内容写入屏幕,但这效......
  • Python - Composition
     classEngine:def__init__(self,power):self.power=powerdefstart(self):self.draw_current()self.spin()self.ignite()defdraw_current(self):print('Drawingcurrent')defspin(sel......
  • Python - Iterator vs Iterable
    Therearemanybuilt-infunctionsandmethodsthatreturniterablesanditerators.Hereareafewexamples:range()returnsaniterabledict.keys()returnsaniterabledict.items()returnsaniterabledict.values()returnsaniterableenumerate()returns......
  • 在python中使用变量引用Panda列名称
    我正在尝试编写一个函数来简化我的代码,因此我传递了包含列名称的变量。它适用于Django应用程序,调试器不会对我的错误所在提供任何反馈,只是“内部服务器错误”。我的代码工作正常,不是作为函数编写的:df_trips['trip_time_prep_starts']=df_trips["trip_time_prep_sta......
  • 如何在 Pyqt5 Python 中实现 QTableWidget 列过滤器中的搜索栏?
    我使用pyqt5创建了一个QTableWidget,并成功地在表格小部件的每一列中添加了过滤选项,并使用堆栈溢出上可用的答案之一。过滤器按预期工作,但我想在顶部的过滤器中添加搜索栏来搜索值。在我的python脚本中,过滤器中可能有大约50多个唯一值。因此,如果有一种方法可以在过滤器......
  • Python - Abstract Base classes
    Wehaveseenthatifwehavetodefineagroupofclassesthathavesimilarfeaturesandshowcommonbehavior,wecandefineabaseclassandtheninherittheclassesfromit.Inthederivedclasses,wehavethechoicetoeitherusethebaseclassversion......
  • python3 unittest+BeautifulReport单个进程输出多个测试报告
    最近一个项目中需要由于输出的案例内容非常多(上万条),导致BeautifulReport输出的报告内容非常大(几百兆)。浏览器无法正常处理这么大的测试报告,就算打开了,也不方便阅读和处理,因此需要将报告分成多个输出。经修改代码,发现单个进程内输出多个测试报告出现问题:第一个测试报告能正常数据......
  • 具有自引用的类装饰器的 Python 类型提示
    我的最终目标是编写一个系统来轻松记录函数调用(特别是类方法)。我首先编写一个带有包装方法的类Loggable,该方法允许我装饰子类方法并记录它们的调用|||现在我可以编写子类并记录它们的调用:Param=ParamSpec("Param")RetType=TypeVar("RetType")CountType=......