I'm trying to make a dict
-like class in Python.
When you make a class, you have certain methods that tell Python how to make a built-in class. For example, overriding the __int__
method tells Python what to return if the user uses int()
on an instance of the class. Same for __float__
. You can even control how Python would make an iterable object of the class by overriding the __iter__
method (which can help Python make list
s and tuple
s of your class). My question is how would you tell Python how to make a dict
of your custom class? There is no special __dict__
method, so how would you go about doing it? I want something like the following:
class Foo():
def __dict__(self):
return {
'this': 'is',
'a': 'dict'
}
foo = Foo()
dict(foo) # would return {'this': 'is', 'a': 'dict'}
I've tried making the class inherit from dict
, but it raises an error later in the code because of subclasses trying to inherit from dict
and type
, so inheriting from dict
isn't a possibility. Is there any other way to do it?
Also, I've overridden the __iter__
method already so that it would return a dict_keyiterator
object (what gets returned when you use iter()
on a dict
), but it still doesn't seem to work how it should.
Actually subclassing dict We can reuse the dict methods through inheritance. All we need to do is create an interface layer that ensures keys are passed into the dict in lowercase form if they are strings. If I override __getitem__ / __setitem__ , then get/set don't work.
Python dict() MethodThe dict() method creates a dictionary object from the specified keys and values, or iterables of keys and values or mapping objects.
The __dict__ in Python represents a dictionary or any mapping object that is used to store the attributes of the object. They are also known as mappingproxy objects. To put it simply, every object in Python has an attribute that is denoted by __dict__.
The dict() function creates a dictionary. A dictionary is a collection which is unordered, changeable and indexed.
Although the approach in the answer from @ForeverWintr is fairly clever and works, I think it's a little obscure since it takes advantage of some of the arcane details about the attributes of the argument passed to the dict
class constructor.
For that reason a better approach might be what I was saying in my comments about just adding a method that does what you want (plus shows how simply giving it a name indicating exactly what's going on makes it more understandable).
Example code:
class Foo:
def to_dict(self):
return {'this': 'is', 'more': 'clear'}
print( Foo().to_dict() ) # -> {'this': 'is', 'more': 'clear'}
dict
can be called with an iterable of pairs, so if you design your __iter__
to return an iterable of tuples, your example works as you'd like:
class Foo:
def __iter__(self):
yield from {
'this': 'is',
'a': 'dict'
}.items()
dict(Foo())
{'a': 'dict', 'this': 'is'}
If you want your class to behave like a python dictionary, in that iterating over an instance iterates over its keys, you can implement the interface defined by abc.Mapping
.
You can do this either by implementing __getitem__
, __iter__
, and __len__
, and inheriting from abc.Mapping
, or by implementing all of __getitem__
, __iter__
, __len__
__contains__
, keys
, items
, values
, get
, __eq__
, and __ne__
.
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