18

Is there a clean/simple way to unpack a Python tuple on the right hand side from left to right?

For example for

j = 1,2,3,4,5,6,7

(1,2,3,4,5,6,7)

v,b,n = j[4:7] 

Can I modify the slice notation so that v = j[6], b=j[5], n=j[4] ?

I realise I can just order the left side to get the desired element but there might be instances where I would just want to unpack the tuple from left to right I think.

martineau
  • 119,623
  • 25
  • 170
  • 301

5 Answers5

51

This should do:

v,b,n = j[6:3:-1]

A step value of -1 starting at 6

Moses Koledoye
  • 77,341
  • 8
  • 133
  • 139
  • 1
    Thanks so much that did it. I tried the same but as an absolute beginner had tried [3:6:-1] not understanding the start stop index needed to be reversed as well – Anthony Lee Meier Jul 09 '16 at 00:46
  • @AnthonyLeeMeier You can also have a look at this thread on [SO](http://stackoverflow.com/questions/509211/explain-pythons-slice-notation) – Moses Koledoye Jul 09 '16 at 01:15
  • 1
    I think maybe `v, b, n = j[:-4:-1]` is better, since it's agnostic about the length of `j`. – Paul Jul 09 '16 at 13:09
14

In case you want to keep the original indices (i.e. don't want to bother with changing 4 and 7 to 6 and 3) you can also use:

v, b, n = (j[4:7][::-1])
Aguy
  • 7,851
  • 5
  • 31
  • 58
  • This works as well thank you for your help. The index of the last element with value 7 is [6] and in yours we range from [4] inclusive to [7] not included. In Moses' answer I think it is similar but ranges from [6] inclusive down to [3] not included. So it seems they both access the same indices and the solution provided by Mosses a bit cleaner I think. Thanks – Anthony Lee Meier Jul 09 '16 at 01:07
10
 n,b,v=j[4:7]

will also work. You can just change the order or the returned unpacked values

joel goldstick
  • 4,393
  • 6
  • 30
  • 46
9

You could ignore the first after reversing and use extended iterable unpacking:

j = 1, 2, 3, 4, 5, 6, 7


_, v, b, n, *_ = reversed(j)

print(v, b, n)

Which would give you:

6 5 4

Or if you want to get arbitrary elements you could use operator.itemgetter:

j = 1, 2, 3, 4, 5, 6, 7

from operator import itemgetter


def unpack(it, *args):
    return itemgetter(*args)(it)

v,b,n = unpack(j, -2,-3,-4)

print(v, b, n)

The advantage of itemgetter is it will work on any iterable and the elements don't have to be consecutive.

Padraic Cunningham
  • 176,452
  • 29
  • 245
  • 321
  • 3
    Well, you can also do `v, b, n = reversed(j[4:7])` without using extended unpacking. this has the benefit that if `j` is long 10 million items the interpreter doesn't have to create new list containing all the other elements. – Bakuriu Jul 09 '16 at 09:22
0

you can try this,

-1 mean looking from reverse, with last 3rd element to last element

>>> v,b,n=j[-1:-4:-1]
>>> print 'v=',v,'b=',b,'n=',n
v= 7 b= 6 n= 5
>>> 
Mohideen bin Mohammed
  • 18,813
  • 10
  • 112
  • 118