Object has no attribute '.__dict__' in python3

雨燕双飞 提交于 2021-02-18 20:11:57

问题


I have a test that passes in Python2 and fails in Python3, I'm trying to find out why. The test fails at the following line:

self._timeseries[0].resource.__dict__

With the error:

AttributeError: 'Resource' object has no attribute '__dict__'

If I debug the test, and print the object in the debugger, I can see the following:

(Pdb) p self._timeseries[0].resource.__dict__
OrderedDict([('type', 'type_value'), ('labels', {'label1': 'value1', 'label2': 'value2', 'label3': 'value3'})])

If I do the same in Python3 debugger, I get this:

(Pdb) p self._timeseries[0].resource.__dict__
*** AttributeError: 'Resource' object has no attribute '__dict__'

Any ideas why this might be happening? The object looks exactly the same if I print it in the debugger without the .__dict__, why is this failing for Python3?


回答1:


So I found the answer after some digging, this indeed is a difference between Python2 and Python3, a nuisant one at that.

It turns out the type Resource in the code is actually a named tuple. In Python2, .__dict__ is added as convenient property wrapper of ._asdict(), but this isn't done in Python3:

https://docs.python.org/2/library/collections.html#collections.somenamedtuple._asdict (find __dict__ here) https://docs.python.org/3/library/collections.html#collections.somenamedtuple._asdict

So it looks like ._asdict is in fact the source of truth, and should be used for portable 2to3 code.

It's worth mentioning that vars is also a wrapper that exists in Python2 only.




回答2:


I wrote a little function, I'm probably missing a few edge cases but it satisfied the few little testcases I wrote (probably broken for multiple inheritance)

class C(object):
    def __init__(self):
        self.x = 1
        self.y = 1


class D(object):
    __slots__ = ('x', 'y')
    def __init__(self):
        self.x = 1
        self.y = 1


class E(D):
    __slots__ = ()


class F(D):
    __slots__ = ('z',)
    def __init__(self):
        super(F, self).__init__()
        self.z = 1


def vars2(x):
    if hasattr(x, '__dict__'):
        return vars(x)
    else:
        ret = {slot: getattr(x, slot) for slot in x.__slots__}
        for cls in type(x).mro():
            spr = super(cls, x)
            if not hasattr(spr, '__slots__'):
                break
            for slot in spr.__slots__:
                ret[slot] = getattr(x, slot)
        return ret


def main():
    print(vars2(C()))
    print(vars2(D()))
    print(vars2(E()))
    print(vars2(F()))
    OUTPUT = '''\
{'y': 1, 'x': 1}
{'y': 1, 'x': 1}
{'y': 1, 'x': 1}
{'y': 1, 'x': 1, 'z': 1}
'''

if __name__ == '__main__':
    exit(main())


来源:https://stackoverflow.com/questions/41658015/object-has-no-attribute-dict-in-python3

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!