2

I have a subclass of dict, but when I am writing it into database, I want to convert it back to a regular dict first. I wanted to use dict(a_instance_of_a_subclass_of_dict) which looks like casting but I need to decide only certain keys are exported to the regular dict.

I don't know what special method of a mapping is called when you write dict(mapping) so I did this experiment:

class Mydict(dict):
    def __getattribute__(self, what):
        print 'getting attribute:', what

m = Mydict(x = 2, y = 3, z = 4)

print '--------- mark ---------'
print dict(m)

It prints:

--------- mark ---------
getting attribute: keys
{'y': 3, 'x': 2, 'z': 4}

It looks like dict(mapping) will call keys method of mapping. (Actually something weird happens here. __getattribute__ returns None here but dict simply didn't rely on the return value and still gets the correct contents. Let's forget about this for now.)

Then I rewrote another subclass of dict like this:

class Mydict2(dict):
    def keys(self):
        print 'here keys'
        return ['x', 'y']

m2 = Mydict2(x = 2, y = 3, z = 4)

print '--------- mark2 ---------'
print dict(m2)

Output is this:

--------- mark2 ---------
{'y': 3, 'x': 2, 'z': 4}

It didn't call keys method. Weird again!

Can somebody explain this behavior? Thanks in advance!

4

1 回答 1

4

cpython 检查是否存在keys来确定参数是否是类似字典的对象:

    if (PyObject_HasAttrString(arg, "keys"))
        result = PyDict_Merge(self, arg, 1);

http://hg.python.org/cpython/file/2.7/Objects/dictobject.c#l1435

但是,在稍后阶段,如果事实证明该参数恰好是一个 dict (或其子类),它不会调用keys,而是直接访问内部哈希表。keys仅对 dict-likes 调用,例如,这按预期工作:

class Mydict2(UserDict):
    def keys(self):
        print 'here keys'
        return ['x', 'y']

我的建议是避免摆弄系统的东西,并添加一个明确的方法,如:

class Mydict2(dict):
    def export(self):
        return {k:self[k] for k in ['x', 'y']}

并在您即将序列化对象以写入数据库时​​调用它。

于 2013-10-29T07:56:32.433 回答