1

I just learnt of unpacking with the * and so went on some test runs. I realized that although some write about passing in tuples as arguments in place of positional arguments, I could also pass in strings, lists and sets and Python wouldn't complain as long as I included the *. I have listed below what I defined as a function taking in positional arguments and the test cases.

What surprised me are the Tracebacks, which led to my question. The Tracebacks mention an IndexError for a tuple even when none is provided. Is what is happening under the hood a casting of the lists, strings and sets into tuples when the * is used?

>>> def print2nd(*args):
...     print(args[1])

>>> s = "abc"
>>> print2nd(*s)
b
>>> print2nd(s)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in print2nd
IndexError: tuple index out of range

>>> t = ['a', 'b', 'c']
>>> print2nd(*t)
b
>>> u = set(['a', 'b', 'c'])
>>> print2nd(*u)
a
>>> print2nd(u)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in print2nd
IndexError: tuple index out of range
>>> u[0]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'set' object does not support indexing
>>> tuple(u)
('b', 'a', 'c')
>>> tuple(u)[1]
'a'
heretoinfinity
  • 1,528
  • 3
  • 14
  • 33
  • Seems so, see [this answer](https://stackoverflow.com/a/26365795/9209546). – jpp Jan 26 '19 at 23:38
  • @jpp, thanks. Would you care to write an answer or should I close the question? – heretoinfinity Jan 26 '19 at 23:40
  • I've marked it as a duplicate for now, since it could be a good marker for others who have the same question. – jpp Jan 26 '19 at 23:42
  • @jpp, could that not lead to downvoting the question? – heretoinfinity Jan 26 '19 at 23:46
  • 1
    I hope not, I actually think it's a useful question (even though an answer on a similar question is sufficient) with different keywords. So it deserves upvoting, in my opinion. – jpp Jan 26 '19 at 23:46
  • @heretoinfinity The single argument you pass in to the function is *not converted* to a tuple but instead *wrapped* by a tuple. That wrapper tuple has as many elements as arguments passed to the function. Since you passed only one argument and `args[1]` attempts to access the second argument there's an `IndexError`. On the other hand `func(*s)` means pass every element of `s` as an argument to `func`. Hence `args` contains the same elements as `s`. – a_guest Jan 27 '19 at 00:17
  • @a_guest, could you clarify the meaning of a wrapper tuple? I am not well versed with wrappers. – heretoinfinity Jan 27 '19 at 16:32
  • 1
    @heretoinfinity It's nothing special, I just used that term to reference the "wrapped by a tuple" part. So it's just an ordinary tuple that's being created and all the arguments are stuffed into it. – a_guest Jan 27 '19 at 17:02

0 Answers0