二级循环字典

时间:2016-09-28 17:17:41

标签: python class for-loop

在构建一个如下所示的out行的类时,我想要for循环的行为,如果完成一次:只需按正常方式键,然后转到下一行代码。但是如果在第一个循环中设置了第二个循环,它将在第一个循环中给出键,然后在第二个循环中的序列中给出ea值。我无法弄清楚的问题是如何在 iter 下设置它。

class MyClass():
    def __init__(self):
        self.cont1 = [1,2,3,4]
        self.cont2 = ('a','b','c')

def __iter__(self):
    pass # ???????

这样的事情:

dct = dict(container1=[5,6,7,8], container2=('a','b','c')

if one loop is used:

   for ea in dct:
        print(ea)
print("Howdy")

'containter1'
'containter2'
Howdy

如果使用嵌套循环:

for ea in dct:
    print(ea)
    for i in dct.get(ea):
        print(i)

'container1'
5
6
...
'container2'
a
b
c

4 个答案:

答案 0 :(得分:1)

要回答您的直接问题,您可以复制字典的实施方式dict.getdict.__iter__

class MyClass():
    def __init__(self):
        self.cont1 = [1,2,3,4]
        self.cont2 = ('a','b','c')

    def __iter__(self):
        for attr in dir(self):
            if not attr.startswith('_') and attr != 'get':
                yield attr

    def get(self, key):
        return getattr(self, key)
然而,这不是一个非常好的方法。在运行时查看对象的属性不是一个好主意,因为它会在您子类化时中断,并且会增加不必要的复杂性。相反,只需在内部使用字典:

class MyClass():
    def __init__(self):
        self.container = {
            'cont1': [1, 2, 3, 4],
            'cont2': ('a', 'b', 'c')
        }

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

    def get(self, key):
        return self.container.get(key)

答案 1 :(得分:0)

你对此感觉如何:

class MyClass():
    def __init__(self):
        self.cont1 = [1,2,3,4]
        self.cont2 = ('a','b','c')
        self.conts = {'container1':self.cont1, 'container2':self.cont2}

    def __iter__(self):
        return self.conts.iteritems()

dct = MyClass()
print('One loop')
for mi in dct:
    print(mi)
print('='*40)
print('Nested loops')
for name, values in dct:
    print(name)
    for i in values:
        print(i)

哪个输出:

One loop
container1
container2
========================================
Nested loops
container1
1
2
3
4
container2
a
b
c

更新

我不知道我真的会推荐这个,但这似乎更符合OP的要求:

class MyIterator(object):
    def __init__(self, name, values):
        self.vals = iter(values)
        self.name = name

    def __iter__(self):
        return self.vals

    def __str__(self):
        return self.name


class MyClass():
    def __init__(self):
        self.cont1 = [1,2,3,4]
        self.cont2 = ('a','b','c')
        self.conts = [MyIterator('container1', self.cont1),
                      MyIterator('container2', self.cont2)]

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

dct = MyClass()
for mi in dct:
    print(mi)
    for i in mi:
        print(i)

这是我能想到的能够打印名称然后作为值列表迭代它的唯一方法。这可以通过覆盖__str__方法来改变对象的获取方式"字符串化"。但正如我之前所说,我认为答案的第一部分会更好。

抱歉,刚刚意识到nauer's answer已经显示过这样的内容。

答案 2 :(得分:0)

您可以使用第二个类

来完成此操作
class MyClass():
    def __init__(self):
        self.data  = [MyClass2({'cont1' : [1,2,3,4]}),MyClass2({'cont2' : ('a','b','c')})]    

    def __iter__(self):
        for item in self.data:
            yield item



class MyClass2():
    def __init__(self, mydict):
        self.d = mydict

    def __iter__(self):
        for item in self.d.values():
            for value in item:
                yield value

    def __repr__(self):
        return(list(self.d.keys())[0])


    m = MyClass()

for k in m:
    print(k)
    for val in k:
        print(val)

答案 3 :(得分:0)

仅通过实施__iter__,您无法做到这一点。 __iter__应该返回一个迭代器,即一个保持迭代状态的对象(项目序列中的当前位置),并且有一个方法next返回每次调用时序列中的下一个项目。

如果您的对象具有嵌套序列,则可以实现仅遍历外部序列的迭代器,或者遍历两者的迭代器 外部序列和内部序列 - 以深度优先或呼吸优先的方式 - 但在同一个迭代中使用嵌套循环没有意义:

# iterate over every item in myobj
for x in myobj:
    ...
    # iterate over every item again? not likely what you want!
    for y in myobj:

更可能的情况是:

for x in myob:
    ...
    for y in x:
        ...