Search code examples
pythonlisttuplesnaming-conventionsiterable-unpacking

*_ and Unpacking Elements from Iterables of Arbitrary Length in python


record= ('ACME', 50, 123.45, (12, 18, 2012))
name, *_, (*_, year) = record 
print(name)
>>>'ACME'
print (year)
>>> 2012
print (*_)
>>> 12 18

So i started reading about unpacking tuples, lists and dictionaries. It said

Sometimes you might want to unpack values and throw them away. You can’t just specify a bare * when unpacking, but you could use a common throwaway variable name, such as _ or ign(ignored)

I didn't quite understand, so I tried to understand by visualizing my code on pythontutor.com but it didn't really "throwaway" the values assigned to *_, also I am unable to access the data " 50, 123.45". I am just starting, so please bear with me cause I am having a hard time understanding this.


Solution

  • "Use a common throwaway variable name" is the clue. *_ is unpacking (*) into a variable named _. The only thing that makes _ "throwaway" is that it is generally ignored. However, if you don't ignore it, it won't be a throwaway!

    If you want to unpack multiple pieces, and still be able to access them separately, use different variable names. Your example:

    >>> record= ('ACME', 50, 123.45, (12, 18, 2012))
    >>> name, *_, (*_, year) = record
    >>> print(name,year,*_)
    ACME 2012 12 18
    

    assigns the variable _ twice, so the later-assigned data 12,18 overwrites the earlier-assigned data 50,123.45. By contrast, consider:

    >>> name, *_a, (*_b, year) = record
    >>> print(*_a)
    50 123.45                 <-- the data you mentioned
    >>> print(*_b)
    12 18
    

    In this example, _a and _b are separate variables that hold separate contents. The assignment

    name, *_a, (*_b, year) = record
    

    is exactly the same as

    name, *extra1, (*extra2, year) = record
    

    but with different names. Again, nothing about _ itself is magical.