So, I'm trying to be a good Python programmer and duck-type wherever I can, but I've got a bit of a problem where my input is either a dict
or a list
of dict
s.
I can't distinguish between them being iterable, because they both are.
My next thought was simply to call list(x)
and hope that returned my list intact and gave me my dict as the only item in a list; alas, it just gives me the list of the dict's keys.
I'm now officially out of ideas (short of calling isinstance
which is, as we all know, not very pythonic). I just want to end up with a list of dicts, even if my input is a single solitary dict.
A string is a sequence of characters. A list a sequence of values which can be characters, integers or even another list (referred to as a nested list). A dictionary is a more general version of a list and is made up a set of keys and values where there is a mapping between a given key and its corresponding value.
List and tuple is an ordered collection of items. Dictionary is unordered collection. List and dictionary objects are mutable i.e. it is possible to add new item or delete and item from it. Tuple is an immutable object.
Dictionaries are similar to lists but are unordered. They do not have index offsets but instead use key-pairs to extract the element.
Really, there is no obvious pythonic way to do this, because it's an unreasonable input format, and the obvious pythonic way to do it is to fix the input…
But if you can't do that, then yes, you need to write an adapter (as close to the input edge as possible). The best way to do that depends on the actual data. If it really is either a dict, or a list of dicts, and nothing else is possible (e.g., you're calling json.loads
on the results from some badly-written service that returns an object or an array of objects), then there's nothing wrong with isinstance
.
If you want to make it a bit more general, you can use the appropriate ABCs. For example:
if isinstance(dict_or_list, collections.abc.Mapping):
return [dict_or_list]
else:
return dict_or_list
But unless you have some good reason to need this generality, you're just hiding the hacky workaround, when you're better off keeping it as visible as possible. If it's, e.g., coming out of json.loads
from some remote server, handling a Mapping
that isn't a dict
is not useful, right?
(If you're using some third-party client library that just returns you "something dict-like" or "something list-like containing dict-like things", then yes, use ABCs. Or, if that library doesn't even support the proper ABCs, you can write code that tries a specific method like keys
. But if that's an issue, you'll know the specific details you're working around, and can code and document appropriately.)
Accessing a dict
using a non-int
key will get you either an item, or a KeyError
. It will get you a TypeError
with a list
. So you can use exception handling:
def list_dicts(dict_or_list):
try:
dict_or_list[None]
return [dict_or_list] # no error, we have a dict
except TypeError:
return dict_or_list # wrong index type, we have a list
except Exception:
return [dict_or_list] # probably KeyError but catch anything to be safe
This function will give you a list
of dicts
regardless of whether it got a list
or a dict
. (If it got a dict
, it makes a list of one item out of it.) This should be fairly safe type-wise, too; other dict
-like or list
-like objects would probably be considered broken if they didn't have similar behavior.
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