python docs将此代码作为zip的反向操作:
>>> x2, y2 = zip(*zipped)
Run Code Online (Sandbox Code Playgroud)
特别是"zip()与*运算符一起使用可以解压缩列表".有人可以向我解释*运算符在这种情况下是如何工作的吗?据我所知,*是一个二元运算符,可用于乘法或浅拷贝......这两者似乎都不是这种情况.
Bla*_*air 61
虽然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
Run Code Online (Sandbox Code Playgroud)
我们可以创建一个列表(或那个元组)来保存它们,然后告诉Python 解包该列表并使用其内容作为函数的参数,而不是直接指定参数:
>>> arguments = [42, 'insert value here', 3.14]
>>> do_something(*arguments)
arg1: 42
arg2: insert value here
arg3: 3.14
Run Code Online (Sandbox Code Playgroud)
如果您没有足够的参数(或太多),则表现正常:
>>> 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)
Run Code Online (Sandbox Code Playgroud)
在定义函数时,可以使用相同的构造来接受任意数量的位置参数.它们作为元组赋予您的功能:
>>> 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
Run Code Online (Sandbox Code Playgroud)
当然,您可以结合使用这两种技术:
>>> show_args(*arguments)
Argument 0: 42
Argument 1: insert value here
Run Code Online (Sandbox Code Playgroud)
您可以使用double asterix(**)和字典对关键字参数执行类似的操作:
>>> 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
Run Code Online (Sandbox Code Playgroud)
当然,您可以通过字典传递关键字参数:
>>> values = {'name': 'John', 'age': 17}
>>> show_kwargs(**values)
age = 17
name = John
Run Code Online (Sandbox Code Playgroud)
混合两者是完全可以接受的,你总是可以为函数提供必需的参数和可选的额外参数:
>>> 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>}
Run Code Online (Sandbox Code Playgroud)
如果您正在使用可选的关键字参数并且您希望拥有默认值,请记住您正在处理字典,因此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>
Run Code Online (Sandbox Code Playgroud)
ham*_*mar 22
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)]
Run Code Online (Sandbox Code Playgroud)
Phi*_*ham 22
当像这样使用时,*(星号,在某些圆圈中也称为"splat"运算符)是从列表中解压缩参数的信号.有关示例,请参阅http://docs.python.org/tutorial/controlflow.html#unpacking-argument-lists以获得更完整的定义.
一旦你真正理解了它的作用,这实际上非常简单zip()。
该zip函数接受多个参数(全部为可迭代类型),并根据这些可迭代项各自的位置对项进行配对。
例如,假设我们有两个参数ranked_athletes, rewards传递给zip,函数调用zip(ranked_athletes, rewards) 将:
reward。这将重复进行,直到不再有运动员或奖励为止。例如,如果我们在 2016 年奥运会上参加 100m 比赛,zip我们获得的奖励是:
ranked_athletes = ["Usain Bolt", "Justin Gatlin", "Andre De Grasse", "Yohan Blake"]
rewards = ["Gold medal", "Silver medal", "Bronze medal"]
zip(ranked_athletes, rewards)
Run Code Online (Sandbox Code Playgroud)
将返回以下元组(对)的迭代器:
('Usain Bolt', 'Gold medal')
('Justin Gatlin', 'Silver medal')
('Andre De Grasse', 'Bronze medal')
Run Code Online (Sandbox Code Playgroud)
请注意Yohan Blake如何没有奖励(因为列表中没有更多奖励rewards)。
该*运算符允许解包列表,例如列表[1, 2]解包为1, 2. 它基本上将一个对象转换为多个对象(与列表的大小一样多)。您可以在此处阅读有关此运算符的更多信息。
因此,如果我们将这两者结合起来,zip(*x)实际上意味着:获取这个对象列表,将其解压缩为许多对象,并根据所有这些对象的索引对项目进行配对。仅当对象是可迭代的(例如列表)时才有意义,否则索引的概念实际上没有意义。
如果您一步步执行,结果如下:
('Usain Bolt', 'Gold medal')
('Justin Gatlin', 'Silver medal')
('Andre De Grasse', 'Bronze medal')
Run Code Online (Sandbox Code Playgroud)
请注意,在这种情况下,如果我们调用,print(list(zip(x)))我们只会将x(这是 2 个列表)中的项目与任何内容配对(因为没有其他可迭代对象可以将它们配对):
[ ([1, 2, 3], ), (['a', 'b', 'c', 'd'], )]
^ ^
[1, 2, 3] is paired with nothing |
|
same for the 2nd item from x: ['a', 'b', 'c', 'd']
Run Code Online (Sandbox Code Playgroud)
理解zip工作原理的另一种好方法是实现您自己的版本,下面的方法或多或少会执行与以下相同的工作,但zip仅限于两个列表(而不是许多可迭代对象)的情况:
>>> print(x) # x is a list of lists
[[1, 2, 3], ['a', 'b', 'c', 'd']]
>>> print(*x) # unpack x
[1, 2, 3] ['a', 'b', 'c', 'd']
>>> print(list(zip(*x))) # And pair items from the resulting lists
[(1, 'a'), (2, 'b'), (3, 'c')]
Run Code Online (Sandbox Code Playgroud)
请注意,我没有调用print(list(zip_two_lists(*x)))它,因为与实际函数不同,这个函数zip不是生成器(构造迭代器的函数),而是我们在内存中创建一个列表。因此这个函数不是那么好,你可以在Python的文档中找到一个更接近真实值的函数zip。阅读本文档中的这些等效代码通常是一个好主意,这是清楚地理解函数功能的好方法。
| 归档时间: |
|
| 查看次数: |
30555 次 |
| 最近记录: |