functools library includes the singledispatch() decorator. It lets you provide a generic function, but provide special cases based on the type of the first argument.
def shuffle(arg, order):
"""this is the generic shuffle function"""
lst = list(arg)
While I do agree with others that Solution 2 is more readable with some improvements, there are also a few improvements that can be done on Solution 1.
It is unnecessary to construct lists from iterables (e.g., generator expressions) when all that is needed is an iterable. For example,
_args = [arg if type(arg)!=dict else arg.items() for arg in args]
I think your solution 2 is heading the right direction here. What I consider it's advantages over solution 1:
It is much more readable
It clearly shows that every member of *args is treated the same.
You might want to generic-ify it a bit more to handle more types. For example, the following has a good chance of also handling custom container types:
To be honest: Neither.
Both are equally unnecessarily complicated and difficult to read. They use old-fashioned, maybe over-optimized techniques instead of Java/OOP features.
The code lacks readable variable names and any documentation for the reader/reviewer or for other programmers who need to use this.
And finally (if I read it correctly) they have ...