Check if the object is dict alike

I needed to check if the object is one of the following types: dict, OrderedDict, defaultdict.

assert all([dictalike(x) for x in [dict(), OrderedDict(), defaultdict()])
assert not any([dictalike(x) for x in [str(), int(), float(), ...])

Several possibilities are functional:

Check for type and type.__bases__ – cause OrderedDict and defaultdict both inherits from dict. = Check if the object is an instance of given class or sublcass.

In [41]: import collections as c
In [42]: [dict in [type(x)] + list(type(x).__bases__) for x in [dict(), c.OrderedDict(), c.defaultdict(), str()]]
Out[42]: [True, True, True, False]

or simply check for __iter__ in dir(x)

In [41]: import collections as c
In [42]: [hasattr(x, '__iter__') for x in [dict(), c.OrderedDict(), c.defaultdict(), str()]]
Out[42]: [True, True, True, True]

or you can use the collections.Iterable

In [41]: import collections as c
In [42]: [isinstance(x, c.Iterable) for x in [dict(), c.OrderedDict(), c.defaultdict(), str()]]
Out[42]: [True, True, True, True]

thought, all three options will get true even for str

The best

The best option would therefore be to check if it’s type collections.Mapping

In [41]: import collections as c
In [42]: [isinstance(x, c.Mapping) for x in [dict(), c.OrderedDict(), c.defaultdict(), str()]]
Out[42]: [True, True, True, False]

The function would be:

from collections import Mapping
def dictalike(obj):
   return isinstance(x, Mapping)

Though it would not check for object iterable via __getitem__

You can write more possible checks to the comments :).

[0] Based on stackoverflow q

Napsat komentář

Vaše e-mailová adresa nebude zveřejněna. Vyžadované informace jsou označeny *