Finding the type of indexing supported by an object?

Peter Otten __peter__ at web.de
Wed Aug 23 06:10:00 EDT 2006


Derek Peschel wrote:

> Here are two functions.
> 
> def invert_dict_to_lists(dict):
>     lists = {}
>     for key in dict:
>         value = dict[key]
>         if not value in lists:
>             lists[value] = [key]
>         else:
>             lists[value].append(key)
>     return lists
> 
> def invert_list_to_lists(list):
>     lists = {}
>     for key in range(len(list)):
>         value = list[key]
>         if not value in lists:
>              lists[value] = [key]
>         else:
>             lists[value].append(key)
>     return lists
> 
> They are the same except for the expression in "for key in ...".  Can they
> be combined into one function?  How can I determine if the argument is
> like a list (with numeric indices that are not stored in the list) or a
> dict
> (with arbitrary keys that are stored)?  I said "object" in the subject,
> but I want to support Python primitive types, class instances, extension
> module types (array, dictproxy, dbm, gdbm, etc.), and any future types.
> 
> I've thought about looking for keys(), looking for the special method
> names that allow you to override indexing behavior, and looking at the
> class or
> type of the object.  I could be wrong, but I don't think any of those
> strategies will work with all arguments.

Instead of the (unreliable) introspection approach you could let the client
code decide:

>>> def invert(pairs):
...     result = {}
...     for k, v in pairs:
...             if v in result:
...                     result[v].append(k)
...             else:
...                     result[v] = [k]
...     return result
...
>>> invert(dict(a=1, b=2, c=1).iteritems())
{1: ['a', 'c'], 2: ['b']}
>>> invert(enumerate([1,1,2,3]))
{1: [0, 1], 2: [2], 3: [3]}

Peter



More information about the Python-list mailing list