Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's the pythonic way to distinguish between a dict and a list of dicts?

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 dicts.

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.

like image 836
Morgan Harris Avatar asked Aug 09 '13 01:08

Morgan Harris


People also ask

What is difference between String list and dictionary?

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.

What is difference between list tuple and dictionary?

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.

What is the difference between dictionaries and lists quizlet?

Dictionaries are similar to lists but are unordered. They do not have index offsets but instead use key-pairs to extract the element.


2 Answers

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.)

like image 190
abarnert Avatar answered Sep 27 '22 23:09

abarnert


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.

like image 45
kindall Avatar answered Sep 27 '22 23:09

kindall