如果班级有__dict__变量,可以检查obj .__ dict__吗?

Bra*_*des 6 python inheritance class introspection internals

我感兴趣的是,是否有一种方法可以无误地反省Python实例,__dict__尽管程序员可能会遇到任何障碍,因为这样可以帮助我调试非预期的引用循环和悬空资源(如打开文件)等问题.

一个更简单的例子是:dict如果程序员隐藏keys()在自己的类后面,我怎么能看到子类的键?解决dict keys()方法是手动调用方法而不是让继承调用子类的方法版本:

# 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']
Run Code Online (Sandbox Code Playgroud)

现在我的实际问题是,__dict__无论程序员可能做了什么来隐藏它,我怎么能看到一个实例呢?如果他们设置了一个__dict__类变量,那么它似乎会影响__dict__从该类继承的任何对象的实际内容:

# My actual question

class DunderDictHider(object):
    __dict__ = {'fake': 'dict'}

ddh = DunderDictHider()
ddh.a = 1
ddh.b = 2
print ddh.a        # prints out 1
print ddh.__dict__ # drat, prints {'fake': 'dict'}
Run Code Online (Sandbox Code Playgroud)

针对这种错误的价值__dict__并不像你所看到的,与实际的属性设置和获取干涉,但它确实误导dir()通过隐藏ab并显示fake为对象的实例变量来代替.

同样,我的目标是编写一个工具,当我想知道为什么一组类实例占用如此多的内存或者保持打开这么多文件时,我可以自省内省类实例以查看"实际发生了什么" - 即使上面的情况是非常人为的,找到解决方法会让工具一直工作,而不是说"工作得很好,除非你正在看的课程有...... [上述特殊情况的描述]."

我以为我能够无懈可击地抓住以下__dict__东西:

dict_descr = object.__dict__['__dict__']
print dict_descr(ddh, DunderDictHider)
Run Code Online (Sandbox Code Playgroud)

但事实证明,object它没有__dict__描述符.相反,subtype_dict()C函数似乎分别附加到object程序员创建的每个子类; 没有集中命名或获取描述符的方法,因此可以手动将其应用于类隐藏它的对象.

任何想法,任何人?:)

Gan*_*ndi 0

这个基于 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
Run Code Online (Sandbox Code Playgroud)

当然,打印不是必需的。

那么让我介绍一下您的新 DunderDictHider:

class DunderDictHider(object):
    __metaclass__ = test_metaclass
    __dict__ = {'fake': 'dict'}
Run Code Online (Sandbox Code Playgroud)

现在您可以通过以下方式访问所有初始化的元素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>}
Run Code Online (Sandbox Code Playgroud)

每次都可以尝试一下

if '__dict__' in repr(DunderDictHider)
Run Code Online (Sandbox Code Playgroud)

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