解压缩和*运算符

python文档给出了这个代码作为zip的反向操作:

>>> x2, y2 = zip(*zipped) 

特别是“zip()与*操作符一起可用于解压缩列表”。 有人可以向我解释*操作符在这种情况下是如何工作的? 据我所知,*是一个二元运算符,可用于乘法或浅拷贝…这两种情况似乎都不是这种情况。

当像这样使用时,*(星号,在一些圆圈中也被称为“splat”运算符)是从列表中解压参数的信号。 请参阅http://docs.python.org/tutorial/controlflow.html#unpacking-argument-lists以获取更完整的示例定义。;

虽然Hammar的答案解释了zip()函数的逆向工作方式, 但从更一般的意义上来看待参数拆包也许是有用的。 假设我们有一个简单的函数需要一些参数:

 >>> 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 

不是直接指定参数,我们可以创build一个列表(或元组)来保存它们,然后告诉Python 解压该列表并将其内容用作函数的参数:

 >>> arguments = [42, 'insert value here', 3.14] >>> do_something(*arguments) arg1: 42 arg2: insert value here arg3: 3.14 

如果您没有足够的参数(或太多),则performance如常:

 >>> 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) 

定义函数时可以使用相同的构造来接受任意数量的位置参数。 它们作为一个元组被赋予你的函数:

 >>> 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 

当然,你可以结合这两种技术:

 >>> show_args(*arguments) Argument 0: 42 Argument 1: insert value here 

你可以用关键字参数做一个类似的事情,使用双星号( ** )和字典:

 >>> 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 

当然,您可以通过字典传递关键字参数:

 >>> values = {'name': 'John', 'age': 17} >>> show_kwargs(**values) age = 17 name = John 

混合两者是完全可以接受的,而且你可以总是有必要的参数和可选的额外参数给一个函数:

 >>> 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>} 

如果您正在使用可选的关键字参数,并且想要使用默认值,请记住您正在处理字典,因此,如果该键不存在,则可以使用其默认值的get()方法:

 >>> 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> 

zip(*zipped)意思是“将zipped每个元素作为参数提供给zip ”。 zip与转置matrix类似,再次做它会让你回到你开始的地方。

 >>> a = [(1, 2, 3), (4, 5, 6)] >>> b = zip(*a) >>> b [(1, 4), (2, 5), (3, 6)] >>> zip(*b) [(1, 2, 3), (4, 5, 6)] 

我build议使用izip_longest完成zip解压缩列表的压缩列表:

 >>> a =[2,3,4,5,6] >>> b = [5,4,3,2] >>> c=[1,0]] >>>[list([val for val in k if val != None]) for k in zip(*itertools.izip_longest(a,b,c))] 

因为izip_longest为最短的列表添加None,所以我先删除None。 我回到原来的a,b,c

 [[2, 3, 4, 5, 6], [5, 4, 3, 2], [1, 0]]