Consider a function defined as:
def fun(a, *args):
print(type(args), args)
When called, it packs the extra positional arguments as a tuple.
>>> fun(2, 3, 4)
<class 'tuple'> (3, 4)
I want to achieve a similar thing outside of function arguments. So, I thought I could achieve the same thing with extended iterable unpacking, but it always packs things as a list and never as a tuple:
# RHS is a tuple
>>> (a, *args) = (2, 3, 4)
>>> type(args)
<class 'list'>
>>> args
[3, 4] #but args is not a tuple!
Making it no different from:
# RHS is a list
>>> (a, *args) = [2, 3, 4]
>>> type(args)
<class 'list'>
>>> args
[3, 4]
I can understand that this is how it is proposed in the PEP as well.
I am asking if there is another way to achieve what I want.
Of course, I could convert args
to tuple by later doing:
>>> args = tuple(args)
>>> args
(3, 4)
If this cannot be achieved directly during the assignment.
Python tuples are immutable means that they can not be modified in whole program. Packing and Unpacking a Tuple: In Python, there is a very powerful tuple assignment feature that assigns the right-hand side of values into the left-hand side. In another way, it is called unpacking of a tuple of values into a variable.
A tuple can also be passed as a single argument to the function. Individual tuples as arguments are just individual variables. A function call is not an assignment statement; it's a reference mapping.
Packing is a technique in python with which we put several values into a single iterator. If we talk of packing in literal terms, Just like we pack certain items into a box in the real world, In python we pack certain variables in a single iterable.
Unpacking in Python refers to an operation that consists of assigning an iterable of values to a tuple (or list ) of variables in a single assignment statement. As a complement, the term packing can be used when we collect several values in a single variable using the iterable unpacking operator, * .
The closest way I know (that I'll admit, doesn't directly answer your question) is just to slice the tuple:
t = (2,3,4)
a, args = t[0], t[1:]
>>> type(args)
<class 'tuple'>
Yes, it's verbose, but at least it avoids the intermediate list.
There are some additional considerations here to keep in mind. The type of the RHS is not restricted to list or tuple. You can unpack an arbitrary iterable:
a, *args = itertools.repeat('hi', 3)
There is no good reason that args
should be either type in particular. It makes sense that the result is a list since it should be able to accumulate an arbitrary number of elements, but there is no major relevant difference in the C code, at least in CPython.
Function arguments pretty much have to be a tuple because the function can return the packed object and a closure. You do not want to be able to modify args
in this case:
def func(arg, *args):
assert args
def blah():
return args[0]
return args, blah
This is a bit contrived, but illustrates why args
can be considered public and should not be mutable in a function.
All that being said, here is a general purpose method for getting the unpacking you want, regardless of the RHS type:
t = (2, 3, 4)
it = iter(t)
a, args = next(it), tuple(it)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With