解压缩和*运算符

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

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

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

如果你没有足够的参数(或者太多),这就像正常情况那样工作:

>>> 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与转置矩阵类似,因为再次执行该操作会使您退回到开始的位置。

>>> 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)]
链接地址: http://www.djcxy.com/p/24027.html

上一篇: Unzipping and the * operator

下一篇: Python: yield