gpt4 book ai didi

python - 我可以在 Python 中迭代一个类吗?

转载 作者:IT老高 更新时间:2023-10-28 20:21:05 26 4
gpt4 key购买 nike

我有一个类在类变量中跟踪其实例,如下所示:

class Foo:
by_id = {}

def __init__(self, id):
self.id = id
self.by_id[id] = self

我想做的是遍历类的现有实例。我可以这样做:

for foo in Foo.by_id.values():
foo.do_something()

但这样看起来会更整洁:

for foo in Foo:
foo.do_something()

这可能吗?我尝试定义一个类方法 __iter__,但没有奏效。

最佳答案

如果你想迭代,你必须定义一个支持迭代的元类。

x.py:

class it(type):
def __iter__(self):
# Wanna iterate over a class? Then ask that class for iterator.
return self.classiter()

class Foo:
__metaclass__ = it # We need that meta class...
by_id = {} # Store the stuff here...

def __init__(self, id): # new isntance of class
self.id = id # do we need that?
self.by_id[id] = self # register istance

@classmethod
def classiter(cls): # iterate over class by giving all instances which have been instantiated
return iter(cls.by_id.values())

if __name__ == '__main__':
a = Foo(123)
print list(Foo)
del a
print list(Foo)

正如你最后看到的,删除一个实例不会对对象本身产生任何影响,因为它保留在 by_id 字典中。你可以使用 weakrefs 当你

import weakref

然后做

by_id = weakref.WeakValueDictionary()

。这样,只要有一个“强”引用保留它,值就会保留,例如 a 在这种情况下。在del a之后,只有指向对象的弱引用,所以可以gc'ed。

由于WeakValueDictionary()s的警告,我建议使用以下:

[...]
self.by_id[id] = weakref.ref(self)
[...]
@classmethod
def classiter(cls):
# return all class instances which are still alive according to their weakref pointing to them
return (i for i in (i() for i in cls.by_id.values()) if i is not None)

看起来有点复杂,但请确保您获得的是对象而不是 weakref 对象。

关于python - 我可以在 Python 中迭代一个类吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10814535/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com