簡體   English   中英

我可以遍歷 Python 中的 class 嗎?

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

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM