[英]Can I iterate over a class in Python?
我有一个 class 跟踪它在 class 变量中的实例,如下所示:
class Foo:
by_id = {}
def __init__(self, id):
self.id = id
self.by_id[id] = self
我想做的是遍历 class 的现有实例。 我可以这样做:
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
dict中。 当你使用weakref
时,你可以应付这种情况
import weakref
然后呢
by_id = weakref.WeakValueDictionary()
。 这样的价值观只会只要有一个“强”引用保持它,比如保持a
在这种情况下。 在del a
,只有弱引用指向该对象,因此它们可以被gc'ed。
由于有关WeakValueDictionary()
的警告,我建议使用以下内容:
[...]
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
对象。
魔术方法总是在类上查找,因此在类中添加__iter__
将不会使其可迭代。 但是,类是其元类的实例,因此元类是定义__iter__
方法的正确位置。
class FooMeta(type):
def __iter__(self):
return self.by_id.iteritems()
class Foo:
__metaclass__ = FooMeta
...
尝试这个:
您可以创建具有全局范围的列表,在主模块中定义列表,如下所示:
fooList = []
然后加:
class Foo:
def __init__(self):
fooList.append(self)
到foo类的init
然后,每次创建Foo类的实例时,它都将被添加到fooList列表中。
现在你所要做的就是迭代这样的对象数组
for f in fooList:
f.doSomething()
您可以创建一个类列表,然后在init方法中调用append,如下所示:
class Planet:
planets_list = []
def __init__(self, name):
self.name = name
self.planets_list.append(self)
用法:
p1 = Planet("earth")
p2 = Planet("uranus")
for i in Planet.planets_list:
print(i.name)
您可以创建一个理解列表,然后调用成员方法,如下所示:
class PeopleManager:
def __init__(self):
self.People = []
def Add(self, person):
self.People.append(person)
class Person:
def __init__(self,name,age):
self.Name = name
self.Age = age
m = PeopleManager()
[[t.Name,t.Age] for t in m.People]
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.