简体   繁体   English

Python 类和 __iter__

[英]Python class and __iter__

What are the benefits of using the __iter__ function in a Python class?在 Python 类中使用__iter__函数有什么好处?

In the code below I am just setting up two simple classes.在下面的代码中,我只是设置了两个简单的类。 The first class takes in a list as an argument, and I am able to loop over this list without using the __iter__ function.第一个类接受一个列表作为参数,我可以在不使用__iter__函数的情况下遍历这个列表。 The second bit of code uses the __iter__ function to loop over a list.代码的第二位使用__iter__函数来循环列表。

What is the benefit of using __iter__ when there are already ways of looping over stuff in a class?当已经有方法循环类中的内容时,使用__iter__有什么好处?

EG 1: no __iter__


class test_class:
    def __init__(self, list):
        self.container_list = list

    def print (self):
        a = self.container_list
        return a

test_list = test_class([1,2,3,4,5,6,7])

x = test_class.print(test_list)

for i in x:
    print (i)



EG 2: yes __iter__

class list_using_iter:
    def __init__(self):
        self.list = [1,2,3,4]
        self.index = -1

    def __iter__(self):
        return self

    def __next__(self):
        self.index += 1
        if self.index == len(self.list):
            raise StopIteration
        return self.list [self.index]

r = list_using_iter()
itr = iter(r)

print(next(itr))
print(next(itr))
print(next(itr))
print(next(itr))

print(next(itr)) # Raises the exception!

Your first example is not iterable, but contains an attribute that is.您的第一个示例不可迭代,但包含一个可迭代的属性。 Your second example is iterable, but you iterate simply by "following" another iterable.您的第二个示例是可迭代的,但您只需“跟随”另一个可迭代对象即可进行迭代。 Here's an example of a iterable that does more work itself:这是一个迭代的例子,它本身做了更多的工作:

import itertools

class Fibs:
    def __init__(self, a, b):
        self.a = a
        self.b = b

    def __iter__(self):
        a = self.a
        b = self.b
        while True:
            yield a
            a, b = b, a + b

real_fibs = Fibs(0,1)

for i in itertools.islice(real_fibs, 10):
    print(i)

Fibs.__iter__ isn't simply regurgitating values obtained from some other value's __iter__ method; Fibs.__iter__不是简单地反刍从其他值的__iter__方法获得的值; it is computing and yielding new values on demand.它根据需要计算并产生新的价值。


Actually, the preceding is an example of a class that knows how to create its own iterator, rather than having each object be iterable.实际上,前面是一个知道如何创建自己的迭代器的类的示例,而不是让每个对象都可迭代。 Here's a version that defines next itself.这是一个定义next本身的版本。

class Fibs:
    def __init__(self, a, b):
        self.a = a
        self.b = b

    def __iter__(self):
        return self

    def __next__(self):
        rv = self.a
        self.a, self.b = self.b, self.a + self.b
        return rv

In both cases, the looping works because of __iter__ .在这两种情况下,循环工作都是因为__iter__ In your first example, your print function returns a loop.在您的第一个示例中,您的打印函数返回一个循环。 The implementation of the for keyword will call __iter__ (or the corresponding slot within the C implementation since the code involved is in the C interpreter) in order to loop over the list. for关键字的实现将调用__iter__ (或 C 实现中的相应槽,因为所涉及的代码在 C 解释器中)以循环遍历列表。

In your second example you could have written在你的第二个例子中,你可以写

for elt in r:
    print(elt)

which would have internally called __iter__ to implement the for loop.它会在内部调用__iter__来实现 for 循环。

In general you tend to use for rather than iter and next directly.一般来说,您倾向于直接使用for而不是iternext The cases where you use iter and next directly are when you're producing a callback function that will produce an iterator or when you're defining one iterator in terms of another.直接使用iternext是当您生成一个将生成迭代器的回调函数时,或者当您根据另一个迭代器定义一个迭代器时。

In terms of when should you write your own __iter__ or return some object that does its own iteration, that all depends on what functionality you want. __iter__何时应该编写自己的__iter__或返回一些进行自己迭代的对象,这一切都取决于您想要什么功能。 For example, your first class is more powerful because two people can be iterating the list at the same time.例如,你的第一个类更强大,因为两个人可以同时迭代列表。 In your second class, because you store the index in the class itself, only one person can successfully use the iterator at a time.在您的第二个类中,由于您将索引存储在类本身中,因此一次只有一个人可以成功使用迭代器。 However, if you had complex enough behavior, the second approach where you define your own __iter__ might make sense.但是,如果您有足够复杂的行为,那么您定义自己的__iter__的第二种方法可能是有意义的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM