[英]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.