The python docs gives this code as the reverse operation of zip:
>>> x2, y2 = zip(*zipped)
In particular
zip() in conjunction with the * operator can be used to unzip a list.
Can someone explain to me how the * operator works in this case? As far as I understand, * is a binary operator and can be used for multiplication or shallow copy...neither of which seems to be the case here.
Basically, it passes the contents of the lists as arguments.
Python's zip() function is defined as zip(*iterables) . The function takes in iterables as arguments and returns an iterator. This iterator generates a series of tuples containing elements from each iterable. zip() can accept any type of iterable, such as files, lists, tuples, dictionaries, sets, and so on.
To unzip a file in Python, use the ZipFile. extractall() method. The extractall() method takes a path, members, pwd as an argument and extracts all the contents.
Although hammar's answer explains how the reversing works in the case of the zip()
function, it may be useful to look at argument unpacking in a more general sense. Let's say we have a simple function which takes some arguments:
>>> def do_something(arg1, arg2, arg3): ... print 'arg1: %s' % arg1 ... print 'arg2: %s' % arg2 ... print 'arg3: %s' % arg3 ... >>> do_something(1, 2, 3) arg1: 1 arg2: 2 arg3: 3
Instead of directly specifying the arguments, we can create a list (or tuple for that matter) to hold them, and then tell Python to unpack that list and use its contents as the arguments to the function:
>>> arguments = [42, 'insert value here', 3.14] >>> do_something(*arguments) arg1: 42 arg2: insert value here arg3: 3.14
This behaves as normal if you don't have enough arguments (or too many):
>>> arguments = [42, 'insert value here'] >>> do_something(*arguments) --------------------------------------------------------------------------- TypeError Traceback (most recent call last) /home/blair/<ipython console> in <module>() TypeError: do_something() takes exactly 3 arguments (2 given)
You can use the same construct when defining a function to accept any number of positional arguments. They are given to your function as a tuple:
>>> def show_args(*args): ... for index, value in enumerate(args): ... print 'Argument %d: %s' % (index, value) ... >>> show_args(1, 2, 3) Argument 0: 1 Argument 1: 2 Argument 2: 3
And of course you can combine the two techniques:
>>> show_args(*arguments) Argument 0: 42 Argument 1: insert value here
You can do a similar thing with keyword arguments, using a double asterix (**
) and a dictionary:
>>> def show_kwargs(**kwargs): ... for arg, value in kwargs.items(): ... print '%s = %s' % (arg, value) ... >>> show_kwargs(age=24, name='Blair') age = 24 name = Blair
And, of course, you can pass keyword arguments through a dictionary:
>>> values = {'name': 'John', 'age': 17} >>> show_kwargs(**values) age = 17 name = John
It is perfectly acceptable to mix the two, and you can always have required arguments and optional extra arguments to a function:
>>> def mixed(required_arg, *args, **kwargs): ... print 'Required: %s' % required_arg ... if args: ... print 'Extra positional arguments: %s' % str(args) ... if kwargs: ... print 'Extra keyword arguments: %s' % kwargs ... >>> mixed(1) Required: 1 >>> mixed(1, 2, 3) Required: 1 Extra positional arguments: (2, 3) >>> mixed(1, 2, 3, test=True) Required: 1 Extra positional arguments: (2, 3) Extra keyword arguments: {'test': True} >>> args = (2, 3, 4) >>> kwargs = {'test': True, 'func': min} >>> mixed(*args, **kwargs) Required: 2 Extra positional arguments: (3, 4) Extra keyword arguments: {'test': True, 'func': <built-in function min>}
If you are taking optional keyword arguments and you want to have default values, remember you are dealing with a dictionary and hence you can use its get()
method with a default value to use if the key does not exist:
>>> def take_keywords(**kwargs): ... print 'Test mode: %s' % kwargs.get('test', False) ... print 'Combining function: %s' % kwargs.get('func', all) ... >>> take_keywords() Test mode: False Combining function: <built-in function all> >>> take_keywords(func=any) Test mode: False Combining function: <built-in function any>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With