Overriding __dict__() on python class
Question:
I have a class where I want to get the object back as a dictionary, so I implemented this in the __dict__()
. Is this correct?
I figured once I did that, I could then use the dict
(custom object), and get back the object as a dictionary, but that does not work.
Should you override __dict__()
? How can you make it so a custom object can be converted to a dictionary using dict()
?
Answers:
__dict__
is not a special method on Python objects. It is used for the attribute dictionary; dict()
never uses it.
Instead, you could support iteration; when dict()
is passed an iterable that produces key-value pairs, a new dictionary object with those key-value pairs is produced.
You can provide an iterable by implementing a __iter__
method, which should return an iterator. Implementing that method as a generator function suffices:
class Foo(object):
def __init__(self, *values):
self.some_sequence = values
def __iter__(self):
for key in self.some_sequence:
yield (key, 'Value for {}'.format(key))
Demo:
>>> class Foo(object):
... def __init__(self, *values):
... self.some_sequence = values
... def __iter__(self):
... for key in self.some_sequence:
... yield (key, 'Value for {}'.format(key))
...
>>> f = Foo('bar', 'baz', 'eggs', 'ham')
>>> dict(f)
{'baz': 'Value for baz', 'eggs': 'Value for eggs', 'bar': 'Value for bar', 'ham': 'Value for ham'}
You could also subclass dict
, or implement the Mapping abstract class, and dict()
would recognize either and copy keys and values over to a new dictionary object. This is a little more work, but may be worth it if you want your custom class to act like a mapping everywhere else too.
No. __dict__
is a method used for introspection – it returns object attributes. What you want is a brand new method, call it as_dict
, for example – that’s the convention. The thing to understand here is that dict
objects don’t need to be necessarily created with dict
constructor.
The following method will allow an object of the class to be casted to a dict
:
def __iter__(self):
for key in self.__dict__:
yield key, getattr(self, key)
I have a class where I want to get the object back as a dictionary, so I implemented this in the __dict__()
. Is this correct?
I figured once I did that, I could then use the dict
(custom object), and get back the object as a dictionary, but that does not work.
Should you override __dict__()
? How can you make it so a custom object can be converted to a dictionary using dict()
?
__dict__
is not a special method on Python objects. It is used for the attribute dictionary; dict()
never uses it.
Instead, you could support iteration; when dict()
is passed an iterable that produces key-value pairs, a new dictionary object with those key-value pairs is produced.
You can provide an iterable by implementing a __iter__
method, which should return an iterator. Implementing that method as a generator function suffices:
class Foo(object):
def __init__(self, *values):
self.some_sequence = values
def __iter__(self):
for key in self.some_sequence:
yield (key, 'Value for {}'.format(key))
Demo:
>>> class Foo(object):
... def __init__(self, *values):
... self.some_sequence = values
... def __iter__(self):
... for key in self.some_sequence:
... yield (key, 'Value for {}'.format(key))
...
>>> f = Foo('bar', 'baz', 'eggs', 'ham')
>>> dict(f)
{'baz': 'Value for baz', 'eggs': 'Value for eggs', 'bar': 'Value for bar', 'ham': 'Value for ham'}
You could also subclass dict
, or implement the Mapping abstract class, and dict()
would recognize either and copy keys and values over to a new dictionary object. This is a little more work, but may be worth it if you want your custom class to act like a mapping everywhere else too.
No. __dict__
is a method used for introspection – it returns object attributes. What you want is a brand new method, call it as_dict
, for example – that’s the convention. The thing to understand here is that dict
objects don’t need to be necessarily created with dict
constructor.
The following method will allow an object of the class to be casted to a dict
:
def __iter__(self):
for key in self.__dict__:
yield key, getattr(self, key)