Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Packing values into a tuple using *, just like function argument packing

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.

like image 303
2020 Avatar asked Dec 16 '19 15:12

2020


People also ask

How do you pack a tuple?

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.

Can a function take a tuple as an argument?

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.

What is the use of packing in Python?

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.

What is argument unpacking in Python?

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, * .


2 Answers

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.

like image 57
Carcigenicate Avatar answered Sep 23 '22 21:09

Carcigenicate


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)
like image 33
Mad Physicist Avatar answered Sep 26 '22 21:09

Mad Physicist