开发者

Extended tuple unpacking in Python 2

开发者 https://www.devze.com 2023-02-18 11:16 出处:网络
Is it possible to simulate extended tuple unpacking in Python 2? Specifically, I have a for loop: for a, b, c in mylist:

Is it possible to simulate extended tuple unpacking in Python 2?

Specifically, I have a for loop:

for a, b, c in mylist:

which works fine when mylist is a list of tuples of size three. I want the same for loop to work if I pass in a list of size four.

I think I will end up using named tuples, but I was wondering if there is an easy way to write:

fo开发者_StackOverflow社区r a, b, c, *d in mylist:

so that d eats up any extra members.


You can't do that directly, but it isn't terribly difficult to write a utility function to do this:

>>> def unpack_list(a, b, c, *d):
...   return a, b, c, d
... 
>>> unpack_list(*range(100))
(0, 1, 2, (3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99))

You could apply it to your for loop like this:

for sub_list in mylist:
    a, b, c, d = unpack_list(*sub_list)


You could define a wrapper function that converts your list to a four tuple. For example:

def wrapper(thelist):
    for item in thelist:
        yield(item[0], item[1], item[2], item[3:])

mylist = [(1,2,3,4), (5,6,7,8)]

for a, b, c, d in wrapper(mylist):
    print a, b, c, d

The code prints:

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


For the heck of it, generalized to unpack any number of elements:

lst = [(1, 2, 3, 4, 5), (6, 7, 8), (9, 10, 11, 12)]

def unpack(seq, n=2):
    for row in seq:
        yield [e for e in row[:n]] + [row[n:]]

for a, rest in unpack(lst, 1):
    pass

for a, b, rest in unpack(lst, 2):
    pass

for a, b, c, rest in unpack(lst, 3):
    pass


You can write a very basic function that has exactly the same functionality as the python3 extended unpack. Slightly verbose for legibility. Note that 'rest' is the position of where the asterisk would be (starting with first position 1, not 0)

def extended_unpack(seq, n=3, rest=3):
    res = []; cur = 0
    lrest = len(seq) - (n - 1)    # length of 'rest' of sequence
    while (cur < len(seq)):
        if (cur != rest):         # if I am not where I should leave the rest
            res.append(seq[cur])  # append current element to result
        else:                     # if I need to leave the rest
            res.append(seq[cur : lrest + cur]) # leave the rest
            cur = cur + lrest - 1 # current index movded to include rest
        cur = cur + 1             # update current position
     return(res)


Python 3 solution for those that landed here via an web search:

You can use itertools.zip_longest, like this:

from itertools import zip_longest

max_params = 4

lst = [1, 2, 3, 4]
a, b, c, d = next(zip(*zip_longest(lst, range(max_params))))
print(f'{a}, {b}, {c}, {d}') # 1, 2, 3, 4

lst = [1, 2, 3]
a, b, c, d = next(zip(*zip_longest(lst, range(max_params))))
print(f'{a}, {b}, {c}, {d}') # 1, 2, 3, None

For Python 2.x you can follow this answer.

0

精彩评论

暂无评论...
验证码 换一张
取 消