【问题标题】:Listing all instance of a class列出类的所有实例
【发布时间】:2015-05-18 08:26:06
【问题描述】:

我编写了一个 Python 模块,其中有几个类继承自一个名为 MasterBlock 的类。 我想在脚本中导入这个模块,创建这些类的几个实例,然后获取这个MasterBlock 类的所有子类的所有现有实例的列表。我找到了vars()['Blocks.MasterBlock'].__subclasses__() 的一些解决方案,但由于我拥有的实例是MasterBlock 的孩子的孩子,所以它不起作用。

下面是一些示例代码:

模块:

Class MasterBlock:
    def main(self):
        pass
Class RandomA(MasterBlock):
    def __init__(self):
        pass
    # inherit the main function
Class AnotherRandom(MasterBlock):
    def __init__(self):
        pass
    # inherit the main function

脚本:

import module
a=module.RandomA()
b=module.AnotherRandom()
c=module.AnotherRandom()
# here I need to get list_of_instances=[a,b,c]

最终目标是能够做到:

for instance in list_of_instances:
    instance.main()

【问题讨论】:

  • @Torxed 这将如何工作?该问题要求提供 instances 的列表,而不是 attributes
  • 像这样使用全局状态通常是个坏主意。在创建 abc 时,最好只跟踪 [a, b, c] 列表。
  • @user2357112 你想如何跟踪这个?我会说问题所要求的自动跟踪是稳健的。
  • @EOL: list_of_instances = [a, b, c]?

标签: python class python-2.7


【解决方案1】:

如果您将如下所示的__new__() 方法添加到您的基类中,该方法跟踪在类变量中创建的所有实例,您可以使该过程或多或少自动化,而不必记住调用某些东西每个子类的__init__()

class MasterBlock(object):
    instances = []
    def __new__(cls, *args, **kwargs):
        instance = super(MasterBlock, cls).__new__(cls, *args, **kwargs)
        instance.instances.append(instance)
        return instance

    def main(self):
        print('in main of', self.__class__.__name__)  # for testing purposes

class RandomA(MasterBlock):
    def __init__(self):
        pass
    # inherit the main function

class AnotherRandom(RandomA):  # works for sub-subclasses, too
    def __init__(self):
        pass
    # inherit the main function

a=RandomA()
b=AnotherRandom()
c=AnotherRandom()

for instance in MasterBlock.instances:
    instance.main()

输出:

in main of RandomA
in main of AnotherRandom
in main of AnotherRandom

【讨论】:

  • 好吧,我对这个问题有太多好的答案了!非常感谢,我不知道 __new__() 这正是我需要的!
  • 不客气。编写类__new__() 方法并不经常需要,但知道它可用以及在创建实例期间何时调用它(如果已定义)在某些情况下可能会有所帮助,如图所示。如果您曾经定义过子类,这也将起作用,顺便说一句。
【解决方案2】:

添加一个包含MasterBlock 的所有实例的类变量怎么样?您可以使用以下方式记录它们:

Class MasterBlock(object):

    all_instances = []  # All instances of MasterBlock

    def __init__(self,…):
        …
        self.all_instances.append(self)  # Not added if an exception is raised before

您可以使用MasterBlock.all_instances(或instance.all_instances)获得MasterBlock 的所有实例。

如果所有基类都调用主类的__init__(通过继承隐式或通过通常的super() 调用显式),则此方法有效。

【讨论】:

  • 我会将all_instances 作为类变量放入类中。
【解决方案3】:

这是一种使用类变量的方法:

class MasterBlock(object):
    instances = []
    def __init__(self):
        self.instances.append(self)
    def main(self):
        print "I am", self

class RandomA(MasterBlock):
    def __init__(self):
        super(RandomA, self).__init__()
        # other init...

class AnotherRandom(MasterBlock):
    def __init__(self):
        super(AnotherRandom, self).__init__()
        # other init...


a = RandomA()
b = AnotherRandom()
c = AnotherRandom()
# here I need to get list_of_instances=[a,b,c]

for instance in MasterBlock.instances:
    instance.main()

(如果子类中不需要__init__,可以让它更简单)

输出:

I am <__main__.RandomA object at 0x7faa46683610>
I am <__main__.AnotherRandom object at 0x7faa46683650>
I am <__main__.AnotherRandom object at 0x7faa46683690>

【讨论】:

  • 这看起来和我的答案一模一样……为什么要添加这个?在我看来,这主要是增加了噪音,应该删除。如果您想明确说明如何使用super(),您可以在评论中这样做,或者您甚至可以编辑我的答案。
  • 因为我是在你发布答案之前写的,所以,嗯,还是贴吧:)
  • 您应该重新加载页面:我的回答比您早 6-3 分钟。 :) 当出现新答案时,StackOverflow 会显示一个横幅。我确实认为你的答案很好,但它本质上是重复的,所以我会删除它,以免浪费阅读它的人的时间(他们不会获得太多新信息)。
  • 嗯,这是一个非常清晰和完整的答案,所以我会接受它!非常感谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-08-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多