使用Python中的类,如何定义一个函数以函数中定义的格式打印类的每个单个实例?
答案 0 :(得分:86)
在这种情况下我看到两个选项:
import gc
for obj in gc.get_objects():
if isinstance(obj, some_class):
dome_something(obj)
这样做的缺点是,当你有很多对象时速度很慢,但是对你无法控制的类型有用。
from collections import defaultdict
import weakref
class KeepRefs(object):
__refs__ = defaultdict(list)
def __init__(self):
self.__refs__[self.__class__].append(weakref.ref(self))
@classmethod
def get_instances(cls):
for inst_ref in cls.__refs__[cls]:
inst = inst_ref()
if inst is not None:
yield inst
class X(KeepRefs):
def __init__(self, name):
super(X, self).__init__()
self.name = name
x = X("x")
y = X("y")
for r in X.get_instances():
print r.name
del y
for r in X.get_instances():
print r.name
在这种情况下,所有引用都存储为列表中的弱引用。如果你经常创建和删除很多实例,你应该在迭代后清理weakrefs列表,否则会有很多错误。
在这种情况下的另一个问题是你必须确保调用基类构造函数。您也可以覆盖__new__
,但只有第一个基类的__new__
方法用于实例化。这也仅适用于您控制的类型。
编辑:根据特定格式打印所有实例的方法留作练习,但它基本上只是for
- 循环的变体。
答案 1 :(得分:22)
您需要在类上创建静态列表,并为每个实例添加weakref
,以便垃圾收集器可以在不再需要实例时清理它们。
import weakref
class A:
instances = []
def __init__(self, name=None):
self.__class__.instances.append(weakref.proxy(self))
self.name = name
a1 = A('a1')
a2 = A('a2')
a3 = A('a3')
a4 = A('a4')
for instance in A.instances:
print(instance.name)
答案 2 :(得分:5)
非常好用且有用的代码,但它有一个很大的问题:列表总是更大并且它永远不会被清理,要测试它只需在末尾添加print(len(cls.__refs__[cls]))
get_instances
方法。
此处修复了get_instances
方法:
__refs__ = defaultdict(list)
@classmethod
def get_instances(cls):
refs = []
for ref in cls.__refs__[cls]:
instance = ref()
if instance is not None:
refs.append(ref)
yield instance
# print(len(refs))
cls.__refs__[cls] = refs
或者可以使用WeakSet完成:
from weakref import WeakSet
__refs__ = defaultdict(WeakSet)
@classmethod
def get_instances(cls):
return cls.__refs__[cls]
答案 3 :(得分:3)
与几乎所有其他OO语言一样,将类的所有实例保存在某种集合中。
你可以试试这种事。
class MyClassFactory( object ):
theWholeList= []
def __call__( self, *args, **kw ):
x= MyClass( *args, **kw )
self.theWholeList.append( x )
return x
现在你可以做到这一点。
object= MyClassFactory( args, ... )
print MyClassFactory.theWholeList
答案 4 :(得分:3)
Python没有与Smallktalk的#allInstances等效,因为该体系结构没有这种类型的中心对象表(尽管现代的小方法也不像这样工作)。
正如另一张海报所说,你必须明确管理一个集合。他建议维护注册表的工厂方法是一种非常合理的方法。您可能希望对weak references执行某些操作,因此您无需明确跟踪对象处理。
答案 5 :(得分:1)
目前尚不清楚是否需要一次打印所有类实例或初始化它们,也不清楚你是否正在谈论一个你可以控制的类与第三方库中的类。
无论如何,我会通过使用Python元类支持编写类工厂来解决这个问题。如果您无法控制班级,请手动更新您正在跟踪的班级或模块的__metaclass__
。
有关详细信息,请参阅http://www.onlamp.com/pub/a/python/2003/04/17/metaclasses.html。
答案 6 :(得分:1)
您无需导入任何内容!只需使用“自我”即可。这是您的操作方式
class A:
instances = []
def __init__(self):
self.__class__.instances.append(self)
@classmethod
def printInstances(cls):
for instance in cls.instances:
print(instance)
A.printInstances()
就是这么简单。没有导入模块或库
答案 7 :(得分:0)
在我的项目中,我遇到了类似的问题,并找到了一个简单的解决方案,该解决方案也可以在列出和打印类实例时为您服务。该解决方案在Python 3.7版中运行顺利;在Python 3.5版中出现了部分错误。
我将从最近的项目中复制并粘贴相关的代码块。
```
instances = []
class WorkCalendar:
def __init__(self, day, patient, worker):
self.day = day
self.patient = patient
self.worker= worker
def __str__(self):
return f'{self.day} : {self.patient} : {self.worker}'
在Python中,最后的__str__
方法确定如何以字符串形式解释对象。我在大括号之间添加了:
,它们完全是我对“ Pandas DataFrame”阅读的偏好。如果应用这个小的__str__
函数,您将看不到一些机器可读的对象类型描述-这对人眼是没有意义的。添加此__str__
函数后,您可以将对象追加到列表中,并根据需要打印它们。
appointment= WorkCalendar("01.10.2020", "Jane", "John")
instances.append(appointment)
对于打印,__str__
中的格式将作为默认格式。但是也可以单独调用所有属性:
for instance in instances:
print(instance)
print(instance.worker)
print(instance.patient)
有关详细阅读,您可以查看以下来源:https://dbader.org/blog/python-repr-vs-str