TAGS :Viewed: 8 - Published at: a few seconds ago

[ Python: how multiple arguments work? ]

I'm new to Python and programming. Can someone explain the following codes in details?

def myzip(*seqs):
    seqs = [list(S) for S in seqs]
    res = []
    while all(seqs):
        res.append(tuple(S.pop(0) for S in seqs))
    return res

>>> myzip([1, 2, 3], ['a', 'b', 'c'])
[(1, 'a'), (2, 'b'), (3, 'c')]

Especially, I don't understand the S is for element in a list (e.g. 1, 2...) or the list ([1, 2, 3]).

I think I need a detail explanation for each line.

Answer 1


In the list comprehension, S is assigned each of the arguments passed to the function; seqs is a list of arguments passed in, and you passed in two lists. So S is first bound to [1, 2, 3] then ['a', 'b', 'c'].

>>> seqs = [[1, 2, 3], ['a', 'b', 'c']]
>>> seqs[0]
[1, 2, 3]

The first line just makes sure that all arguments are turned into lists, explicitly, so that you can later on call list.pop(0) on each. This allows you to pass in strings, tuples, dictionaries, or any other iterable as an argument to this function:

>>> myzip('123', 'abc')
[('1', 'a'), ('2', 'b'), ('3', 'c')]

The while all(seqs): loop then iterates until there is at least one argument that is empty. In other words, the loop terminates when the shortest sequence has been exhausted:

>>> myzip('1', 'abc')
[('1', 'a')]

In the loop, the first element of each of the input arguments is removed from the list and added to res as a tuple. For the 2 input lists, that means that first (1, 'a') is added to res, followed by (2, 'b') then (3, 'c').

Answer 2


seqs is the list of two separate lists: [1,2,3] and ['a', 'b', 'c']

Now while all(seqs): will iterate through the elements of seqs - the two lists mentioned above. We then create an empty list res and append to it tuple objects. Each tuple object will progressively contain the first element of each of the list in seqs. pop(0) will return the first element and remove it from the list thus changing the list in place (lists are mutable).

Thus what you are doing is you are creating a list of tuples obtained by pairing the corresponding elements in both the lists.

When you say seqs = [list(S) for S in seqs], S refers to each of the list element in seqs. However, in this particular call to the function, since you are passing lists as elements this statement becomes redundant.

Answer 3


First You need to know what is zip function. Because this function is doing the same job as zip in python.

def myzip(*seqs):

First line says this function gets as many argument you want and all of them will be gather in one list as seqs. Usage like myzip([1, 2, 3], ['a', 'b', 'c']) gives you seqs = [[1, 2, 3], ['a', 'b', 'c']].

    seqs = [list(S) for S in seqs]

Then you want to make sure every item in seqs are list items. This line convert every item to list. This is what list does. (Even '123' to ['1', '2', '3'])

    res = []
    while all(seqs):
        res.append(tuple(S.pop(0) for S in seqs))
    return res

In these four lines it pops first element of each S of seqs and creates a tuple for final result. The final result is a list (res = []). In the loop condition: all(seqs) it checks if all elements of seqs are available. If one them goes empty it breaks the loop. In side the loop, pop(0) removes the first element from S and return it as value S.pop(0). This way it updates all elements of seqs. for next loop.

tuple creates tuple like (1, 'a') out of all first elements. Next iteration is going to be `(2, 'b') because all first elements popped before.

All these tuples in a list res is its goal. res.append adds these tuple to the final result.