iter迭代无线循环错误

我在阅读werkzeug中实现的flask Header类的时候,碰到了这个装饰器。

def native_itermethods(names):

    def setmethod(cls, name):
        itermethod = getattr(cls, name)
        setattr(cls, 'iter%s' % name, itermethod)
        listmethod = lambda self, *a, **kw: list(itermethod(self, *a, **kw))
        listmethod.__doc__ = \
            'Like:py:meth:`iter%s`, but returns a list.' % name
        setattr(cls, name, listmethod)

    def wrap(cls):
        for name in names:
            setmethod(cls, name)
        return cls
    return wrap

这部分代码会对该类下创建一个iter开头的方法。比如get会创建出一个iterget。并把原来的get的返回值改为迭代iterget的列表。这是我理解的如果有错误请指正。

我想要对上边的装饰器进行测试验证以下是我的代码

iterget = lambda d, *arg, **kw: d.iterget(*arg, **kw)

@native_itermethods(['get'])
class A(object):

    def __init__(self):
        self._names = [('mink', '123'), ('kk', '1211')]

    def __iter__(self):
        yield iter(self._names)

    def get(self, name):
        for key, value in iterget(self):
            if key == name:
                yield key, value
                
if __name__ == '__main__':
    a = A()
    print dir(a)
    print a.get('mink')

按照我的理解上面装饰器的结果应该返回一个元组列表,但是会爆出以下错误
图片描述

是我例子写错了么还是,我对上述代码没有理解对。

阅读 3.5k
1 个回答

首先是这个不是无限循环,而是递归超过了栈深度。

在 native_itermethods 里面,会把外面的A.get放在作为A对象iterget方法,并且用list(A.iterget)覆盖原来的A.get。在你的A.get定义里面,由于A.get已经调用了A.iterget,这其实就会是自身调用自身,会无限的递归下去,从而导致栈溢出错误。

这个函数的目的主要是方便把对象里原来的迭代器方法的名字变成itername,然后让原来的名字返回一个list后的结果。

推荐问题