是否有一些内省方法可以可靠地获取对象实例的基础数据结构,不受任何自定义的影响?
在Python 3中,对象的低级实现可能会被深深掩盖:属性查找可以自定义,甚至__dict__
和__slots__
属性也可能无法提供完整的图片,因为它们是可写的。 dir()
明确表示显示“有趣”属性而非实际属性,甚至inspect
模块似乎也不提供此类功能。
答案 0 :(得分:4)
没有什么是完全通用的,特别是对于用 C 实现的对象。Python 类型只是没有为通用解决方案存储足够的实例布局元数据。也就是说,即使面对非常奇怪的 Python 级修改(包括删除或隐藏的插槽描述符以及删除或隐藏的 __dict__
描述符),gc.get_referents
也非常可靠。
gc.get_referents
会给所有引用一个对象报告给垃圾收集系统。它不会告诉你为什么一个对象有一个特定的引用——它不会告诉你一个 dict 是 __dict__
一个 dict 是一个不相关的插槽,碰巧有一个输入它。
例如:
import gc
class Foo:
__slots__ = ('__dict__', 'a', 'b')
__dict__ = None
def __init__(self):
self.x = 1
self.a = 2
self.b = 3
x = Foo()
del Foo.a
del Foo.b
print(gc.get_referents(x))
for name in '__dict__', 'x', 'a', 'b':
try:
print(name, object.__getattribute__(x, name))
except AttributeError:
print('object.__getattribute__ could not look up', name)
这个打印
[2, 3, {'x': 1}, <class '__main__.Foo'>]
__dict__ None
x 1
object.__getattribute__ could not look up a
object.__getattribute__ could not look up b
gc.get_referents
设法检索真实的实例字典以及 a
和 b
槽,即使相关的描述符都丢失了。不幸的是,它没有提供有关它检索到的任何引用的含义的信息。
object.__getattribute__
无法检索实例字典或 a
或 b
槽。它确实设法找到x
,因为它在检索其他属性时不依赖于__dict__
描述符来查找实例字典,但是您需要已经知道{{ 1}} 是您应该查找的名称 - x
无法发现您应该在此对象上查找哪些名称。
答案 1 :(得分:0)
user202729 在评论中建议使用 object.__getattribute__(obj, "field")
。
围绕此构建自定义函数(使用 object.__getattribute__(obj,"__dict__")
和 object.__getattribute__(obj,"__slots__")
)似乎符合我将内部数据转储到文档稀疏的代码上的初衷。
然而,也有人指出,事情可能会更加混乱,或者对于用 C 实现的类来说是不可访问的。