通过一个对象迭代两次

时间:2018-04-11 21:18:46

标签: python python-3.x

我试图创建一个可迭代对象,当我做一个循环时它没关系,但是当做多个循环时,它不起作用。这是我的简化代码:

class test():

    def __init__(self):
        self.n = 0

    def __iter__(self):
        return self

    def __next__(self):
        if self.n < len(self)-1:
            self.n += 1
            return self.n
        else:
            raise StopIteration

    def __len__(self):
        return 5

#this is an example iteration
test = test()
for i in test:
    for j in test:
        print(i,j)

#it prints is 
1 2
1 3
1 4

#What i expect is
1 1 
1 2
1 3
1 4
2 1
2 2
2 3
...
4 3
4 4

如何使此对象(在本例中为test)迭代两次,并在示例循环中获取数字ij的所有组合?

2 个答案:

答案 0 :(得分:3)

您希望test的实例是可迭代的,而不是它自己的迭代器。有什么区别?

可迭代是根据请求可以提供迭代器的东西。列表是可迭代的,因为iter([1,2,3])返回一个新的listiterator对象(列表本身)。要使test可迭代,您只需要提供__iter__方法(更多关于如何定义它的内容)。

迭代器是根据请求可以生成新元素的东西。它通过调用其__next__方法来实现此目的。迭代器可以被认为是两条信息:要生成的项目序列,以及指示它当前在该序列上有多远的光标。当它到达序列的末尾时,它会引发StopIteration异常以指示迭代结束。要使实例成为迭代器,请在其类中提供__next__方法。迭代器也应该有一个只返回自己的__iter__方法。

那么如何在不作为迭代器的情况下使test迭代?通过让__iter__方法在每次调用时返回一个新的迭代器,并删除它的__next__方法。最简单的方法是使__iter__成为生成器函数。将您的课程定义为:

class Test():

    def __init__(self):
        self._size = 5

    def __iter__(self):
        n = 0
        while n < self._size:
            yield n
            n += 1

    def __len__(self):
        return self._size

现在写的时候

test = Test()
for i in test:    # implicit call to iter(test)
    for j in test:  # implicit call to iter(test)
        print(i, j)

ij都在同一个迭代中从单独的迭代器中绘制值。每次调用test.__iter__都会返回一个不同的生成器对象,用于跟踪自己的n

答案 1 :(得分:0)

看看itertools.product

你应该能够完成你正在寻找的东西:

var Handlebars = require('Handlebars');
var i18n = require('i18n');

module.exports = {
    //Setup our default layout
    defaultLayout: 'default',

    //Register handlebars helpers
    helpers: {
    //Register your helpers
        //Helper for multiple languages
        i18n: function () {
            return i18n.__.apply(this, arguments);
        },
        __n: function () {
            return i18n.__n.apply(this, arguments);
        },
        section: function (name, options) {
            if (!this._sections) this._sections = {};
            this._sections[name] = options.fn(this);
            return null;
        }, 
        breaklines: function(text) {
            text = Handlebars.Utils.escapeExpression(text);
            text = text.replace(/(\r\n|\n|\r)/gm, '<br>');
            return new Handlebars.SafeString(text);
        }
    }     
}

我喜欢这个图书馆!