In my work, my Python scripts get a lot of input from non-Python-professional users. So, for example, if my function needs to handle both single values and a series of values (Polymorphism/Duck Typing, Yo!) I would like to do something like this pseudo-code:
def duck_typed(args):
"""
args - Give me a single integer or a list of integers to work on.
"""
for li in args:
<do_something>
If the user passes me a list:
[1,2]
a tuple:
(1,2)
or even a singleton tuple (terminology help here, please)
(1,)
everything works as expected. But as soon as the user passes in a single integer everything goes to $%^&:
1
TypeError: 'int' object is not iterable
The Difference between Smart and Clever
Now, I immediately think, "No problem, I just need to get clever!" and I do something like this:
def duck_typed(args):
"""
args - Give me a single integer or a list of integers to work on.
"""
args = (args,) # <= Ha ha! I'm so clever!
for li in args:
<do_something>
Well, now it works for the single integer case:
args = (1,)
(1,)
but when the user passes in an iterable, the $%^&*s come out again. My trick gives me a nested iterable:
args = ((1,2),)
((1,2),)
ARGH!
The Usual Suspects
There are of course the usual workarounds. Try/except clauses:
try:
args = tuple(args)
except TypeError:
args = tuple((args,))
These work, but I run into this issue A LOT. This is really a 1-line problem and try/except is a 4-line solution. I would really love it if I could just call:
tuple(1)
have it return (1,) and call it a day.
Other People Use this Language Too, You Know
Now I'm aware that my needs in my little corner of the Python programming universe don't apply to the rest of the Python world. Being dynamically typed makes Python such a wonderful language to work in -- especially after years of work in neurotic languages such as C. (Sorry, sorry. I'm not bashing C. It's quite good at what its good at, but you know: xkcd)
I'm quite sure the creators of the Python language have a very good reason to not allow tuple(1)
.
Question 1
Will someone please explain why the creators chose to not allow tuple(1)
and/or list(1)
to work? I'm sure its completely sane reason and bloody obvious to many. I may have just missed it during my tenure at the School of Hard Knocks. (It's on the other side of the hill from Hogwarts.)
Question 2
Is there a more practical -- hopefully 1-line -- way to make the following conversion?
X(1) -> (1,)
X((1,2)) -> (1,2)
If not, I guess I could just break down and roll my own.