Python:使类可迭代

新手上路,请多包涵

我继承了一个项目,其中包含许多仅由类对象(整数、字符串等)组成的大类。我希望能够检查属性是否存在,而无需手动定义属性列表。

是否可以使用标准语法使 python 自身可迭代?也就是说,我希望能够使用 for attr in Foo: (甚至 if attr in Foo )迭代所有类的属性,而无需先创建类的实例。我想我可以通过定义 __iter__ 来做到这一点,但到目前为止我还没有完全管理我正在寻找的东西。

通过添加 __iter__ 方法,我已经实现了一些我想要的,如下所示:

 class Foo:
    bar = "bar"
    baz = 1
    @staticmethod
    def __iter__():
        return iter([attr for attr in dir(Foo) if attr[:2] != "__"])

但是,这并不能完全满足我的要求:

 >>> for x in Foo:
...     print(x)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'classobj' object is not iterable

即便如此,这仍然有效:

 >>> for x in Foo.__iter__():
...     print(x)
bar
baz

原文由 multipleinterfaces 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 429
2 个回答

添加 __iter__ 到元类而不是类本身(假设 Python 2.x):

 class Foo(object):
    bar = "bar"
    baz = 1
    class __metaclass__(type):
        def __iter__(self):
            for attr in dir(self):
                if not attr.startswith("__"):
                    yield attr

对于 Python 3.x,使用

class MetaFoo(type):
    def __iter__(self):
        for attr in dir(self):
            if not attr.startswith("__"):
                yield attr

class Foo(metaclass=MetaFoo):
    bar = "bar"
    baz = 1

原文由 Sven Marnach 发布,翻译遵循 CC BY-SA 4.0 许可协议

这就是我们使类对象可迭代的方式。为类提供一个 迭代 器和一个 next() 方法,然后您可以迭代类属性或它们的值。如果您愿意,可以保留 next() 方法,或者您可以定义 next() 并在某些条件下引发 StopIteration .

例如:

 class Book(object):
      def __init__(self,title,author):
          self.title = title
          self.author = author

      def __iter__(self):
          for each in self.__dict__.values():
              yield each

>>> book  = Book('The Mill on the Floss','George Eliot')
>>> for each in book: each
...
'George Eliot'
'The Mill on the Floss'

此类迭代 Book 类的属性值。类对象也可以通过为其提供 getitem 方法来使其可迭代。例如:

 class BenTen(object):
    def __init__(self, bentenlist):
        self.bentenlist = bentenlist

    def __getitem__(self,index):
        if index <5:
            return self.bentenlist[index]
        else:
            raise IndexError('this is high enough')

>>> bt_obj = BenTen([x for x in range(15)])
>>>for each in bt_obj:each
...
0
1
2
3
4

现在,当 BenTen 类的对象在 for-in 循环中使用时,getitem 将以连续更高的索引值调用,直到引发 IndexError。

原文由 vijay shanker 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题