【问题标题】:How to iterate over `dict` in class like if just referring to `dict`?如何在类中迭代“dict”,就像只引用“dict”一样?
【发布时间】:2015-05-15 23:53:49
【问题描述】:

在定义的对象中,一些值保存在dict 中,我想在引用普通dict 时迭代dict 中的内容,因此可以使用[] 直接访问,并且使用例如循环.items()。代码结构为:

class Klass:

    def __init__(self, values):
        self.values = values
        self.more = None

    def __getitem__(self, name):
        return self.values[name]

    def __iter__(self):
        pass  # TBD[How to make this ?]

d = {'alfa': 1, 'bravo': 2, 'charlie': 3}

k = Klass(d)

for key in k:
    print(key)  # Expected to print keys from self.values 

for (key, value) in k.items():
    print(key, value)  # Expected to print key and value from self.values 

for key in k.keys():
    print(key)  # Expected to print key from self.values 

for value in k.values():
    print(value)  # Expected to print value from self.values 

如何编写__iter__ 和其他必需的方法,以便通过Klass 的实例进行这种访问?

【问题讨论】:

  • for item in self.values: yield item?
  • OOP 的意图是隐藏具体的实现,所以应该避免直接引用实例属性.values..
  • @EquipDev:在实现中你仍然必须依赖你自己的状态。 Torxed 提出了 __iter__ 的实现,使其成为生成器函数。不过这里不需要,iter() 不需要。
  • @MartijnPieters:现在我明白了;是的,这符合 OOP 原则。感谢您指出这一点。

标签: python python-3.x dictionary iterator


【解决方案1】:

您必须自己实现.keys().values().items() 方法;与__iter__ 一起,他们都可以将实际工作委托给self.values() 字典:

class Klass:
    def __init__(self, values):
        self._values = values
        self.more = None

    def __getitem__(self, name):
        return self._values[name]

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

    def keys(self):
        return self._values.keys()

    def items(self):
        return self._values.items()

    def values(self):
        return self._values.values()

我重命名了属性以避免掩盖.values() 方法。

委派__iter__ 对字典进行迭代(按键)的最简单方法是使用iter() function 获取字典对象的迭代器。

明确地说:__iter__.keys().values().items() 的处理方式中没有任何作用;后者只是更多的方法

【讨论】:

  • 感谢您的帮助,并将values 重命名为_values;当必须实现 values 方法时,这是一个错误的名称选择。
  • 没有必要实现.keys()等。只需从collections.abc.Mapping继承。
  • @Kevin:是的,这是下一步。 collections.abc.Mapping 然后实现了这些方法这一事实并没有减少需要实现这些方法的事实。
【解决方案2】:
    class Klass(dict):
        def __init__(self, *arg, **kw):
            super(Klass, self).__init__(*arg, **kw)
            self.choosebettername = super(Klass, self).keys()

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

        def keys(self):
            return self.choosebettername

        def itervalues(self):
            return (self[key] for key in self)


    d = {'alfa': 1, 'bravo': 2, 'charlie': 3}

    k = Klass(d)

    for key in k:
        print(key)  # Expected to print keys from self.values 

    for (key, value) in k.items():
        print(key, value)  # Expected to print key and value from self.values 

    for key in k.keys():
        print(key)  # Expected to print key from self.values 

    print(k.values())

    for value in k.values():
        print(value)  # Expected to print value from self.values 

【讨论】:

    猜你喜欢
    • 2013-11-03
    • 1970-01-01
    • 2015-02-28
    • 2020-09-07
    • 2019-02-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-30
    相关资源
    最近更新 更多