kdb*_*kdb 6 python introspection python-3.x
是否有一些内省方法允许可靠地获取对象实例的底层数据结构,不受任何自定义的影响?
在 Python 3 中,对象的低级实现可以被深深地掩盖:属性查找可以自定义,甚至__dict__和__slots__属性也可能无法提供完整的图片,因为它们是可写的。dir()明确表示要显示“有趣”的属性而不是实际属性,甚至该inspect模块似乎也不提供此类功能。
不是重复的。此问题已标记为重复是否有内置函数可以打印对象的所有当前属性和值?. 然而,另一个问题只讨论了自省类的标准方法,这里明确列出了在较低级别上不可靠的方法。
作为示例,请考虑以下带有故意模糊类的脚本。
import inspect
actual_members = None # <- For showing the actual contents later.
class ObscuredClass:
def __init__(self):
global actual_members
actual_members = dict()
self.__dict__ = actual_members
self.actual_field = "actual_value"
def __getattribute__(self, name):
if name == "__dict__":
return { "fake_field": "fake value - shown in __dict__" }
else:
return "fake_value - shown in inspect.getmembers()"
obj = ObscuredClass()
print(f"{actual_members = }")
print(f"{dir(obj) = }")
print(f"{obj.__dict__ = }")
print(f"{inspect.getmembers(obj) = }")
Run Code Online (Sandbox Code Playgroud)
产生输出
actual_members = {'actual_field': 'actual_value'}
dir(obj) = ['fake_field']
obj.__dict__ = {'fake_field': 'fake value - shown in __dict__'}
inspect.getmembers(obj) = [('fake_field', 'fake_value - shown in inspect.getmembers()')]
Run Code Online (Sandbox Code Playgroud)
没有什么是完全通用的,特别是对于用 C 实现的对象。Python 类型只是没有为通用解决方案存储足够的实例布局元数据。也就是说,gc.get_referents即使面对非常奇怪的 Python 级别的修改(包括删除或隐藏的槽描述符以及删除或隐藏的__dict__描述符),它也是相当可靠的。
gc.get_referents会将对象的所有引用报告给垃圾收集系统。不过,它不会告诉你为什么一个对象有一个特定的引用 - 它不会告诉你一个字典是一个字典__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)
Run Code Online (Sandbox Code Playgroud)
这打印
[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
Run Code Online (Sandbox Code Playgroud)
gc.get_referents即使相关描述符全部丢失,也能设法检索真实实例字典以及a和插槽。b不幸的是,它没有提供有关它检索到的任何引用的含义的信息。
object.__getattribute__无法检索实例字典或a或b槽。它确实设法找到x,因为它在检索其他属性时不依赖__dict__描述符来查找实例字典,但您需要已经知道x您应该查找的名称 -object.__getattribute__无法发现您应该查找的名称这个物体。
| 归档时间: |
|
| 查看次数: |
129 次 |
| 最近记录: |