【问题标题】:How does this class implement the "__iter__" method without implementing "next"?这个类如何在不实现“next”的情况下实现“__iter__”方法?
【发布时间】:2010-12-29 22:33:04
【问题描述】:

我在 django.template 中有以下代码:

class Template(object):
    def __init__(self, template_string, origin=None, name='<Unknown Template>'):
        try:
            template_string = smart_unicode(template_string)
        except UnicodeDecodeError:
            raise TemplateEncodingError("Templates can only be constructed from unicode or UTF-8 strings.")
        if settings.TEMPLATE_DEBUG and origin is None:
            origin = StringOrigin(template_string)
        self.nodelist = compile_string(template_string, origin)
        self.name = name

    def __iter__(self):
        for node in self.nodelist:
            for subnode in node:
                yield subnode

    def render(self, context):
        "Display stage -- can be called many times"
        return self.nodelist.render(context)

我感到困惑的部分如下。这个__iter__ 方法是如何工作的?我找不到任何对应的next 方法。

def __iter__(self):
        for node in self.nodelist:
            for subnode in node:
                yield subnode

这是我知道如何实现__iter__的唯一方法:

class a(object):
    def __init__(self,x=10):
        self.x = x
    def __iter__(self):
        return self
    def next(self):
        if self.x > 0:
            self.x-=1
            return self.x
        else:
            raise StopIteration
 ainst = a()
 for item in aisnt:
     print item

在你的回答中,尽量使用代码示例而不是文字,因为我的英语不是很好。

【问题讨论】:

    标签: python iterator yield


    【解决方案1】:

    来自docs

    如果容器对象的__iter__() 方法被实现为生成器, 它会自动返回一个 迭代器对象(技术上,一个 生成器对象)提供 __iter__()__next__() 方法。

    这是您提供的使用生成器的示例:

    class A():
        def __init__(self, x=10):
            self.x = x
        def __iter__(self):
            for i in reversed(range(self.x)):
                yield i
    
    a = A()
    for item in a:
        print(item)
    

    【讨论】:

      【解决方案2】:

      __iter__method 返回一个 python generator(参见documentation),因为它使用了yield 关键字。 生成器会自动提供 next() 方法;引用文档:

      生成器如此紧凑的原因在于创建了 __iter__() 和 next() 方法 自动。

      编辑:

      生成器真的很有用。如果您不熟悉它们,我建议您阅读它们,并尝试一些测试代码。

      这里是来自StackOverflow 的有关迭代器和生成器的更多信息。

      【讨论】:

      • 是客户端代码调用的意思吗?我假设不是,因为它具有 fname 形式
      • --fname-- 这些破折号是下划线的形式
      • 我对Django一无所知,但最终它只是python语法。当需要为 Template 对象创建迭代器时,将调用其 __iter__(self) 钩子。然后它将返回一个具有正确 next() 方法的 Generator 对象。
      • @danben:你不叫obj.__iter__(),你叫iter(obj)iter(obj) 将转换为对 obj.__iter__() 的调用(如果已定义),就像 Foo() 将转换为对 Foo.__init__() 的调用(如果已定义)。
      • __x__ 形式的方法/成员变量在 python 中通常具有特殊含义(例如__dict____builtin__)。尝试迭代对象时调用对象的__iter__ 方法,例如在for .. in ..: 循环中。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多