Python 迭代器自定义类,包装在OrderedDict上,对下一步感到困惑__

Python 迭代器自定义类,包装在OrderedDict上,对下一步感到困惑__,python,python-3.x,iteration,Python,Python 3.x,Iteration,我意识到我仍然不太理解如何实现迭代器类。因此,一个类可以对其某些内容进行“for循环” 我已经看过这些答案(我仍然不明白): 据我所知,iterable是一个实现\uuuuu iter\uuuuuu并返回迭代器的函数,迭代器是已实现\uuuu next\uuuuu的函数。 从这一点上,我不知何故理解了,如果我希望我的类是一个迭代器,并且是iterable。我必须定义\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu以返回self,并定义\uuuuuuuuuuuuuuu

我意识到我仍然不太理解如何实现迭代器类。因此,一个类可以对其某些内容进行“for循环”

我已经看过这些答案(我仍然不明白):

据我所知,iterable是一个实现
\uuuuu iter\uuuuuu
并返回迭代器的函数,迭代器是已实现
\uuuu next\uuuuu
的函数。 从这一点上,我不知何故理解了,如果我希望我的类是一个迭代器,并且是iterable。我必须定义
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
以返回self,并定义
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu。到目前为止我错了吗

这是我班的脚手架:

class Wrapper:
    def __init__(self, low, high):
        self.store = OrderedDict()  # it is imported (ommited)

    def __getitem__(self, key):
        return self.store[key]

    def __iter__(self):
        return self
        # Option 3
        return self.store

    def __next__(self):
        # Option 1 
        for key in self.store:
            return key
        # Option 2
        for key in self.store.keys():
            return key
尝试了上述选项,但均无效:(

发生的事情是我准备了一些py.tests来测试迭代是否正确,只是一个简单的for循环,没有什么特别的。测试只是永远运行(或者比我的耐心<5分钟更长),但是mock类有5个项,所以不会花太长时间


我做错了什么?

您可以进行以下更改:

class Wrapper:
    def __init__(self, low, high):
        self.store = OrderedDict() 
        self.__iter = None  # maintain state of self as iterator

    def __iter__(self):
        if self.__iter is None:
            self.__iter = iter(self.store)
        return self

    def __next__(self):
        try:
            return next(self.__iter)
        except StopIteration:   # support repeated iteration
            self.__iter = None  
            raise
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
方法应返回
self
,以正确实现协议。这可确保在循环期间调用
next
将迭

for x in wrapper:
    # do stuff with x
    next(wrapper)  # skip one
在大多数情况下,插入
\uuuu iter\uuu
就足够了:

class Wrapper:
    def __init__(self, low, high):
        self.store = OrderedDict() 

    def __iter__(self):
        return iter(self.store)

您可以进行以下更改:

class Wrapper:
    def __init__(self, low, high):
        self.store = OrderedDict() 
        self.__iter = None  # maintain state of self as iterator

    def __iter__(self):
        if self.__iter is None:
            self.__iter = iter(self.store)
        return self

    def __next__(self):
        try:
            return next(self.__iter)
        except StopIteration:   # support repeated iteration
            self.__iter = None  
            raise
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
方法应返回
self
,以正确实现协议。这可确保在循环期间调用
next
将迭

for x in wrapper:
    # do stuff with x
    next(wrapper)  # skip one
在大多数情况下,插入
\uuuu iter\uuu
就足够了:

class Wrapper:
    def __init__(self, low, high):
        self.store = OrderedDict() 

    def __iter__(self):
        return iter(self.store)

你说,你的概念搞混了

我意识到我仍然不太理解如何实现一个迭代器类。因此,一个可以对其某些内容进行“for循环”的类

但事情不是这样的。如果您只想在类的实例上执行
for
循环,几乎可以肯定的是,您不应该让实例直接成为迭代器。您应该编写一个
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
方法,手动或通过
yield
ing返回迭代器,而不应该编写
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu下一步

# Returning an iterator manually:
class Wrapper:
    ...
    def __iter__(self):
        return iter(self.store)

# or with yield:
class Wrapper:
    ...
    def __iter__(self):
        for thing in self.store:
            yield thing
迭代器在技术上是可迭代的,但只能使用一次。要编写迭代器,您必须
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
返回
self
,并在每次调用时
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu.我将在半开放区间[0,10]上编写迭代器,因为为OrderedICT编写迭代器只会将所有内容委托给OrderedICT的迭代器,因为这太直接了,不具有指导意义:

class Iterator:
    def __init__(self):
        self.state = 0
    def __iter__(self):
        return self
    def __next__(self):
        if self.state == 10:
            raise StopIteration
        self.state += 1
        return self.state - 1
但是,即使您确实需要迭代器,手动编写迭代器也是不寻常的;使用
yield

def iterator():
    for i in range(10):
        yield i

# or managing the index manually, to show what it would be like without range:
def iterator():
    i = 0
    while i < 10:
        yield i
        i += 1
def迭代器():
对于范围(10)内的i:
产量一
#或者手动管理索引,以显示没有范围时的情况:
def迭代器():
i=0
当我<10时:
产量一
i+=1

你的概念混淆了。你说

我意识到我仍然不太理解如何实现一个迭代器类。因此,一个可以对其某些内容进行“for循环”的类

但事情不是这样的。如果您只想在类的实例上执行
for
循环,几乎可以肯定的是,您不应该让实例直接成为迭代器。您应该编写一个
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
方法,手动或通过
yield
ing返回迭代器,而不应该编写
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu下一步

# Returning an iterator manually:
class Wrapper:
    ...
    def __iter__(self):
        return iter(self.store)

# or with yield:
class Wrapper:
    ...
    def __iter__(self):
        for thing in self.store:
            yield thing
迭代器在技术上是可迭代的,但只能使用一次。要编写迭代器,您必须
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
返回
self
,并在每次调用时
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu.我将在半开放区间[0,10]上编写迭代器,因为为OrderedICT编写迭代器只会将所有内容委托给OrderedICT的迭代器,因为这太直接了,不具有指导意义:

class Iterator:
    def __init__(self):
        self.state = 0
    def __iter__(self):
        return self
    def __next__(self):
        if self.state == 10:
            raise StopIteration
        self.state += 1
        return self.state - 1
但是,即使您确实需要迭代器,手动编写迭代器也是不寻常的;使用
yield

def iterator():
    for i in range(10):
        yield i

# or managing the index manually, to show what it would be like without range:
def iterator():
    i = 0
    while i < 10:
        yield i
        i += 1
def迭代器():
对于范围(10)内的i:
产量一
#或者手动管理索引,以显示没有范围时的情况:
def迭代器():
i=0
当我<10时:
产量一
i+=1

谢谢,这工作得很好。在没有状态维护的情况下,它似乎也能工作。您能解释一下为什么需要它吗?您可以在包装器中为x执行
(隐式调用
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu),但是
下一个(包装器)
(隐式调用
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu如果不维护状态,则无法正常工作。
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu迭代器协议。因为这个类定义了迭代器,
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu>必须返回
self
。很可能,OPmethod@user2357112你到底是什么意思?是的我的类定义是错误的,但Schwobasegll解决方案似乎使它工作得非常完美。谢谢,这项工作