Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unneeded parts when unwrapping tuple/list

Python is all about writing beautiful code. So, I was running pylint to check the "beautifulness" of my code, when I bump into something:

Unused variable 'myvar1'

From this part of my code:

for myvar1, myvar2 in mylist:
    # Do stuff just using myvar2

mylist is a list of tuples, so I'm unwrapping the tuples into two variables (myvar1 and myvar2). I'm defining those two variables just to unwrap the second one, because I don't need the other.

So, here's my question: Is there a way to tell the interpreter to unwrap the tuple, but not assing the first part (for example). In some other languages you can do something like:

for _, myvar in mylist:
    # Do stuff with myvar

or

for *, myvar in mylist:
    # Do stuff with myvar

That means: I don't care about the first part of the tuple, I just need the second one.

NOTE: I know that this could be an option for what I'm asking:

for mytuple in mylist:
    # Do stuff with mytuple[1]

But that's by far less readable.

like image 916
juliomalegria Avatar asked Dec 02 '11 19:12

juliomalegria


People also ask

How do I unpack a list of tuples?

If you want to unzip your list of tuples, you use the combination of zip() method and * operator.

How does tuple unpacking work in Python?

Unpacking Tuples When we put tuples on both sides of an assignment operator, a tuple unpacking operation takes place. The values on the right are assigned to the variables on the left according to their relative position in each tuple . As you can see in the above example, a will be 1 , b will be 2 , and c will be 3 .

What do you mean by packing and unpacking of tuples?

Tuple packing refers to assigning multiple values into a tuple. Tuple unpacking refers to assigning a tuple into multiple variables.

When would you use multiple assignment statement to unpack a tuple?

Multiple assignment (also known as tuple unpacking or iterable unpacking) allows you to assign multiple variables at the same time in one line of code. This feature often seems simple after you've learned about it, but it can be tricky to recall multiple assignment when you need it most.


5 Answers

In addition to @RaymondHettinger's answer: Pylint also does not complain about unused variables if their names start with a single underscore. This means that you can use:

for _myvar1, myvar2 in mylist:

getting the best of both worlds:

  • no Pylint warning,
  • and information about the record structure

This works for function / method prototypes too and avoids warnings about unused parameters, which you can often get when deriving from a base class in an OO framework.

like image 181
gurney alex Avatar answered Oct 04 '22 00:10

gurney alex


Did you try either of these?

for _, myvar in mylist:
    #Do stuff

works fine in Python and is relatively idiomatic.

like image 32
Wilduck Avatar answered Oct 04 '22 02:10

Wilduck


I write for _, myvar2 in mylist when I want to emphasize that only myvar2 is used.

And I write for myvar1, myvar2 in mylist when I want to remind the reader (usually me) what the record structure is.

The _ name is just a naming convention for a throw-away value. The CPython interpreter makes the variable assignment for it just like it would with any other variable name (fortunately, *STORE_FAST* is a very cheap operation). In contrast, the PyPy interpreter will identify the unused variable assignment as dead code, so you get the optimization for free regardless of how you write it.

If you're curious about how CPython interprets your code, the dis module can provide useful insights:

>>> from dis import dis
>>> def f(lot):
        for _, var2 in lot:
            print var2


>>> dis(f)
  2           0 SETUP_LOOP              25 (to 28)
              3 LOAD_FAST                0 (lot)
              6 GET_ITER            
        >>    7 FOR_ITER                17 (to 27)
             10 UNPACK_SEQUENCE          2
             13 STORE_FAST               1 (_)
             16 STORE_FAST               2 (var2)

  3          19 LOAD_FAST                2 (var2)
             22 PRINT_ITEM          
             23 PRINT_NEWLINE       
             24 JUMP_ABSOLUTE            7
        >>   27 POP_BLOCK           
        >>   28 LOAD_CONST               0 (None)
             31 RETURN_VALUE 

As the other posters have mentioned, the warnings from pylint can sometimes be inane. If you prefer a short variable name in your code, then just ignore the pylint complaint. As Francis Avila pointed out, pylint should't complain about _ in this context.

like image 24
Raymond Hettinger Avatar answered Oct 04 '22 00:10

Raymond Hettinger


I suppose you could do this:

for myvar in (t[1] for t in mylist):
    pass

But frankly I think you should just ignore the pylint warning in this case--it's beautiful enough and won't cause any confusion (which is why you want to beauty in the first place).

like image 42
Francis Avila Avatar answered Oct 04 '22 02:10

Francis Avila


I would say Python is all about writing readable code - any "beauty" is merely a side-effect.

The first item of the tuple could be eliminated like this:

for myvar2 in zip(*mylist)[1]:
    # Do stuff with myvar2

But I'm not sure I'd really recommend it. Personally I would just use:

for myvar1, myvar2 in mylist:
    # Do stuff with myvar2

... and ignore pylint.

like image 34
ekhumoro Avatar answered Oct 04 '22 00:10

ekhumoro