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?
__dict__ is A dictionary or other mapping object used to store an object's (writable) attributes. Or speaking in simple words every object in python has an attribute which is denoted by __dict__. And this object contains all attributes defined for the object.
All objects in Python have an attribute __dict__, which is a dictionary object containing all attributes defined for that object itself. The mapping of attributes with its values is done to generate a dictionary.
AttrDict , Attribute Dictionary, is the exact same as a python native dict , except that in most cases, you can use the dictionary key as if it was an object attribute instead. This allows users to create container objects that looks as if they are class objects (as long as the user objects the proper limitations).
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.
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())
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With