Generic dictionary
Steve D'Aprano
steve+python at pearwood.info
Sun Nov 20 05:10:08 EST 2016
On Sun, 20 Nov 2016 08:27 pm, Thorsten Kampe wrote:
> I'd like to extend the dictionary class by creating a class that acts
> like a dictionary if the class is instantiated with a dictionary and
> acts like a "dictitem" ([(key1, value1), (key2, value2), ...]) if
> instantiated with a list (that is dictitem).
I'm not sure exactly what you are trying to accomplish here. You want a
single class that sometimes behaves like a dict, and sometimes behaves like
a list? Not just any list, but specifically a list of tuples of two items.
Frankly, that sounds... weird. Generally speaking, classes don't behave
differently according to how they are created. Consider:
float(123) # int argument
float("123") # str argument
The object you get back is the same, regardless of whether the class was
instantiated from an int or a str. That's a general principle of Object
Oriented Programming: an object's behaviour should depend on *what it is*,
not where it came from.
> The code (see extract at bottom) works well but it contains a lot of
> "if this is a dictionary then do as a dictionary already does"
> boilerplate code". How can I "inherit"(?)/"subclass"(?)/derive from
> dict so I don't have to write the code for the dictionary case?
class MyDict(dict):
pass
inherits from dict. But that won't do what you want, since a dict doesn't
behave anything like a list of tuples. You'll have to over-ride
*everything*, filling your code with horrible stuff like this:
class MyDict(dict):
def __init__(self, *args, **kwargs):
super(MyDict, self).__init__(*args, **kwargs)
# Decide whether to act like a list or a dict.
if args and isinstance(args[0], dict):
self._act_like_dict = True
else:
self._act_like_dict = False
def __getitem__(self, key_or_index):
if self._act_like_dict:
# treat like a key
super(MyDict, self).__getitem__(key_or_index)
else:
# treat like an index
tmp = list(self.values())
return tmp[key_or_index]
def update(self, *args, **kwargs):
if self._act_like_dict:
super(MyDict, self).update(*args, **kwargs)
else:
raise TypeError('list doesn't support update')
def sort(self, *args, **kwargs):
if self._act_like_dict:
raise TypeError('dict doesn't support sort')
else:
# somehow re-implement list sorting for something
# which is like a dict
...
Etc. It would be a monstrous pain in the posterior to write, and confusing
to use. Are you sure you want this? The whole concept of a class that
behaves differently depending on how you create it feels to me like that
movie "The Fly".
I think that a better strategy would be to reconsider. Why not just write
your code to accept *either* a dict, or a list of tuples? Then you don't
have to invent some monstrous hybrid class that is like the product of an
awful teleportation accident.
--
Steve
“Cheer up,” they said, “things could be worse.” So I cheered up, and sure
enough, things got worse.
More information about the Python-list
mailing list