【问题标题】:Defining magic methods on classes在类上定义魔术方法
【发布时间】:2025-12-04 16:40:01
【问题描述】:

我想定义一个可以迭代的对象,而不必创建类和实例。像这样的:

class Thing(object):
    stuff = ["foo", "bar", "baz"]

    @classmethod
    def __iter__(cls):
        return iter(cls.stuff)

for thing in Thing:
    print thing

但是这实际上不起作用。有没有办法做到这一点?

【问题讨论】:

  • 对于一个类,在元类上定义__iter__
  • 魔术方法查找发生在类上。因此,您要么必须创建实例和类,要么必须创建类和元类。但似乎你也可以只是子类列表(至少在你的例子中)。
  • @jedwards 好的,我试图避免在我的模块的命名空间中创建额外的东西,但我想我只需要处理它。这是一个非常简化的示例,在我的实际用例中,内部状态不仅仅是一个列表。

标签: python magic-methods


【解决方案1】:

Ashwini 在他的评论中正确建议如下。这适用于 Python 2。

class ThingType(type):
    __stuff__ = ["foo", "bar", "baz"]

    @classmethod
    def __iter__(cls):
        return iter(cls.__stuff__)

class Thing(object):
    __metaclass__ = ThingType

for thing in Thing:
    print thing

这适用于 Python 3:

class ThingType(type):
    __stuff__ = ["foo", "bar", "baz"]

    @classmethod
    def __iter__(cls):
        return iter(cls.__stuff__)

class Thing(object, metaclass=ThingType):
    pass

for thing in Thing:
    print(thing)

【讨论】:

  • 我的错,错过了stuff的位置。 ://
  • 它会起作用,因为(即使没有类方法)Python 可以通过在 MRO 中查找来找到属性。早些时候我误读了它,并认为您在Thing 中定义了stuff 而不是ThingType。所以... ;-)
【解决方案2】:

Thing 真的需要是一个类型吗?您可以将其设为具有类似类型的可调用行为的对象,这可能会更简单:

class RealThing(object):
  pass

class ThingFactory(object):
  def __iter__(self):
    return iter(["foo", "bar", "baz"])

  def __call__(self):
    return RealThing()

Thing = ThingFactory()

【讨论】: