I recently created a @sequenceable decorator, that can be applied to any function that takes one argument, and causes it to automatically be applicable to any sequence. This is the code (Python 2.5):
def sequenceable(func):
def newfunc(arg):
if hasattr(arg, '__iter__'):
if isinstance(arg, dict):
return dict((k, func(v)) for k, v in arg.iteritems())
else:
return map(func, arg)
else:
return func(arg)
return newfunc
In use:
@sequenceable
def unixtime(dt):
return int(dt.strftime('%s'))
>>> unixtime(datetime.now())
1291318284
>>> unixtime([datetime.now(), datetime(2010, 12, 3)])
[1291318291, 1291352400]
>>> unixtime({'start': datetime.now(), 'end': datetime(2010, 12, 3)})
{'start': 1291318301, 'end': 1291352400}
My questions are:
- Is this a terrible idea, and why?
- Is this a possibly good idea, but has significant drawbacks as implemented?
- What are the potential pitfalls of
using this code? - Is there a builtin or library that
already does what I’m doing?
This is a terrible idea. This is essentially loose typing. Duck-typing is as far as this
stuff should be taken, IMO.
Consider this:
Your example then becomes
Doing it this way still requires the caller to know (to within duck-typing accuracy) what is being passed in and doesn’t add any typechecking overhead to the actual function. It will also work with any dict-like object whereas your original solution depends on it being an actual subclass of
dict.