在知道类名时是否有任何方法可以获取对象名称。如果一个类有多个对象,则还需要打印它们。
Class A():
pass
假设某些人在其他一些文件中为A类创建了对象。所以,我想查看“A类”的所有实例
答案 0 :(得分:2)
如果您是创建类的人,则可以在实例化类时简单地存储弱引用:
import weakref
class A(object):
instances = []
def __init__(self):
A.instances.append(weakref.ref(self))
a, b, c = A(), A(), A()
instances = [ref() for ref in A.instances if ref() is not None]
使用弱引用允许在类之前释放实例。
有关其功能的详细信息,请参阅weakref
模块。
请注意,即使您没有编写的类,也可以使用此技术。你只需要 monkey-patch 这个类。 例如:
def track_instances(cls):
def init(self, *args, **kwargs):
getattr(self, 'instances').append(weakref.ref(self))
getattr(self, '_old_init')(self, *args, **kwargs)
cls._old_init = cls.__init__
cls.__init__ = init
return cls
然后你可以这样做:
track_instances(ExternalClass)
在执行此语句之后创建的所有实例都将在ExternalClass.instances
中找到。
根据课程的不同,您可能需要替换__new__
而不是__init__
。
即使没有类中的任何特殊代码,只需使用垃圾收集器即可实现此目的:
import gc
candidates = gc.get_referrers(cls_object)
instances = [candidate for candidate in candidates if isinstance(candidate, cls_object)]
您可以随时获取类对象,因为您可以使用object.__subclasses__
方法找到它:
cls_object = next(cls for cls in object.__subclasses__() if cls.__name__ == cls_name)
(假设只有一个具有该名称的类,否则你应该尝试所有这些)
但是,我无法想到这是正确的事情,所以在实际应用程序中避免使用此代码。
我已经完成了一些测试,我相信这个解决方案可能不适用于C扩展中定义的内置类或类。
如果您是这种情况,最后的手段将使用gc.get_objects()
来检索所有跟踪的对象。但是,这仅在对象支持循环垃圾收集时才有效,因此没有一种方法可以在每个可能的情况下工作。
答案 1 :(得分:1)
这里是从内存中获取实例的版本,我不建议在实时代码中使用它,但它可以方便调试:
import weakref
class SomeClass(object):
register = []
def __init__(self):
self.register.append(weakref.ref(self))
a = SomeClass()
b = SomeClass()
c = SomeClass()
# Now the magic :)
import gc
def get_instances(class_name):
# Get the objects from memory
for instance in gc.get_objects():
# Try and get the actual class
class_ = getattr(instance, '__class__', None)
# Only return if the class has the name we want
if class_ and getattr(class_, '__name__', None) == class_name:
yield instance
print list(get_instances('SomeClass'))
答案 2 :(得分:0)
>>> class TestClass:
... pass
...
>>> foo = TestClass()
>>> for i in dir():
... if isinstance(eval(i), TestClass):
... print(i)
...
foo
>>>
答案 3 :(得分:0)
在命名空间中创建实例:
def some_function():
some_object = MyClass()
在这种情况下,some_object
是指向MyClass
实例的函数“命名空间”内的名称。一旦你离开命名空间(即函数结束),Python的垃圾收集会清除名称和实例。
如果某个其他位置也有指向该对象的指针,则不会进行清理。
所以:不,没有维护实例列表的地方。
将数据库与ORM(对象关系映射器)一起使用将是一种不同的情况。在Django的ORM中,如果MyClass是数据库对象,则可以MyClass.objects.all()
。如果你真的需要这个功能,可以考虑一下。
更新:请参阅Bakuriu's answer。垃圾收集器(我提到过)知道所有实例:-)而且他建议使用“weakref”模块来阻止我不会被清理的问题。
答案 4 :(得分:0)
Python提供了types
模块,它定义了内置类型的类,以及locals()
和globals()
函数,它们返回应用程序中的局部变量和全局变量列表。
按类型查找对象的一种快速方法是执行此操作。
import types
for varname, var_instance in locals().items():
if type(var_instance) == types.InstanceType and var_instance.__class__.__name__ == 'CLASS_NAME_YOU_ARE_LOOKING_FOR':
print "This instance was found:", varname, var_instance
值得浏览Python库文档并阅读直接使用代码的模块的文档。其中一些是inspect
,gc
,types
,codeop
,code
,imp
,ast
。 bdb
,pdb
。 IDLE源代码也非常有用。
答案 5 :(得分:0)
你可以获得所有实例的名称,因为它们可能都没有名称,或者它们所拥有的名称可能在范围内。您可以获得实例。
如果您愿意自己跟踪实例,请使用WeakSet:
import weakref
class SomeClass(object):
instances = weakref.WeakSet()
def __init__(self):
self.instances.add(self)
>>> instances = [SomeClass(), SomeClass(), SomeClass()]
>>> other = SomeClass()
>>> SomeClass.instances
<_weakrefset.WeakSet object at 0x0291F6F0>
>>> list(SomeClass.instances)
[<__main__.SomeClass object at 0x0291F710>, <__main__.SomeClass object at 0x0291F730>, <__main__.SomeClass object at 0x028F0150>, <__main__.SomeClass object at 0x0291F210>]
请注意,删除名称可能不会破坏实例。在收集垃圾之前,other
仍然存在:
>>> del other
>>> list(SomeClass.instances)
[<__main__.SomeClass object at 0x0291F710>, <__main__.SomeClass object at 0x0291F730>, <__main__.SomeClass object at 0x028F0150>, <__main__.SomeClass object at 0x0291F210>]
>>> import gc
>>> gc.collect()
0
>>> list(SomeClass.instances)
[<__main__.SomeClass object at 0x0291F710>, <__main__.SomeClass object at 0x0291F730>, <__main__.SomeClass object at 0x0291F210>]
如果您不想手动跟踪它们,则可以使用gc.get_objects()
并过滤掉您想要的实例,但这意味着每次您必须过滤程序中的所有对象做这个。即使在上面的例子中,这意味着处理近12,000个对象以找到你想要的3个实例。
>>> [g for g in gc.get_objects() if isinstance(g, SomeClass)]
[<__main__.SomeClass object at 0x0291F210>, <__main__.SomeClass object at 0x0291F710>, <__main__.SomeClass object at 0x0291F730>]
答案 6 :(得分:0)
终于找到了通过的方法。
我知道类名,我会在垃圾收集器(gc)中搜索为该类创建的对象......
for instance in gc.get_objects():
if str(type(instance)).find("dict") != -1:
for k in instance.keys():
if str(k).find("Sample") != -1:
return k
上面的代码返回类的实例,它将是这样的。不幸的是,它的String格式不符合要求。它应该是'obj'类型。
<mod_example.Sample object at 0x6f55250>
从上面的值中解析id(0x6f55250)并根据id获取对象引用。
obj_id = 0x6f55250
for obj in gc.get_objects():
# Converting decimal value to hex value
if id(obj) == ast.literal_eval(obj_id):
required_obj = obj
因此,required_obj将完全以'obj'格式保存对象引用。
: - )