如果类中有一个变量,是否可以检查对象dict?

2024-09-28 22:33:10 发布

您现在位置:Python中文网/ 问答频道 /正文

我感兴趣的是,是否有一种方法可以无误地反省Python实例以查看它的__dict__,尽管程序员可能会在这一过程中抛出任何障碍,因为这将帮助我调试诸如意外引用循环和悬空资源(如打开的文件)之类的问题。在

一个简单的例子是:如果程序员在自己的类后面隐藏了dict子类的键呢?解决方法是手动调用dictkeys()方法,而不是让继承调用子类的方法版本:

# Simple example of getting to the real info
# about an instance

class KeyHidingDict(dict):
    def keys(self):
        return []  # there are no keys here!

khd = KeyHidingDict(a=1, b=2, c=3)
khd.keys()       # drat, returns []
dict.keys(khd)   # aha! returns ['a', 'b', 'c']

现在我的实际问题是,我如何才能看到实例的__dict__,不管程序员做了什么来隐藏它?如果他们设置了一个__dict__类变量,那么它似乎会隐藏从该类继承的任何对象的实际__dict__

^{pr2}$

如您所见,__dict__的这个假值不会干扰实际的属性设置和获取,但是它确实误导了dir(),它隐藏了a和{},并将{}显示为对象的实例变量。在

同样,我的目标是编写一个工具,帮助我反省类实例,以便在我想知道为什么一组类实例占用了这么多内存或打开了这么多文件时查看“到底发生了什么”—尽管上面的情况非常复杂,找到一种方法可以让这个工具一直工作,而不是说“工作很好,除非你正在看的类有…[上面对异常情况的描述]”

我原以为我可以用这样的东西毫无疑问地抓住__dict__

dict_descr = object.__dict__['__dict__']
print dict_descr(ddh, DunderDictHider)

但是结果发现object没有__dict__描述符。相反,subtype_dict()C函数似乎是分别附加到程序员创建的object的每个子类上;没有中央方法来命名或获取描述符,因此它可以手动应用于类隐藏它的对象。在

有什么想法吗?:)


Tags: 文件工具对象实例方法object手动keys
2条回答

这是基于Jerub在本主题中的回答: What is a metaclass in Python?

你可以用元类实现你想要的。在

首先需要创建一个元类:

def test_metaclass(name, bases, dict):
    print 'The Class Name is', name
    print 'The Class Bases are', bases
    print 'The dict has', len(dict), 'elems, the keys are', dict.keys()

    return dict

当然指纹不是必须的。在

那么让我介绍一下你的新邓德克希德:

^{pr2}$

现在您可以通过repr(DunderDictHider)访问所有已初始化的元素

输出(使用print repr(DunderDictHider)行):

The Class Name is DunderDictHider
The Class Bases are (<type 'object'>,)
The dict has 3 elems, the keys are ['__dict__', '__module__', '__metaclass__']
{'__dict__': {'fake': 'dict'}, '__module__': '__main__', '__metaclass__': <function test_metaclass at 0x1001df758>}

每次你都可以试试

if '__dict__' in repr(DunderDictHider)

知道这个类是否试图隐藏它的__dict__。记住,repr输出是一个字符串。它可以做得更好,但这就是想法本身。在

我不确定我是否满意这样简单:

>>> class DunderDictHider(object):
...     __dict__ = {'fake': 'dict'}
... 
>>> ddh = DunderDictHider()
>>> ddh.a = 1
>>> ddh.b = 2
>>> 
>>> print ddh.a
1
>>> print ddh.__dict__
{'fake': 'dict'}

问题是这个班作弊?修好它!在

^{pr2}$

就在这里。但是,如果类定义了任何插槽,则完全失败。在

>>> class DoesntHaveDict(object):
...     __slots__ = ['a', 'b']
... 
>>> dhd = DoesntHaveDict()
>>> dhd.a = 1
>>> dhd.b = 2
>>> 
>>> print dhd.a
1
>>> dhd.__class__ = DictUnhider
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: __class__ assignment: 'DoesntHaveDict' object layout differs from 'DictUnhider'
>>> 

相关问题 更多 >