简体   繁体   English

在 zip function 之前使用星号

[英]Using an asterisk to precede the zip function

The below code is from Jake VanderPlas's book "Python Data Science Handbook":以下代码来自 Jake VanderPlas 的《Python 数据科学手册》一书:

rand = np.random.RandomState(42)
X = rand.rand(10,2)
dist_sq = np.sum(X[:,np.newaxis,:] - X[np.newaxis,:,:]) ** 2, axis=-1)    

K=2
nearest_partition = np.argpartition(dist_sq, K + 1, axis=1)

plt.scatter(X[:, 0], X[:, 1], s=100)
# draw lines from each point to its two nearest neighbors
for i in range(X.shape[0]):
    for j in nearest_partition[i, :K+1]:
        # plot a line from X[i] to X[j]
        # use some zip magic to make it happen:
        plt.plot(*zip(X[j], X[i]), color='black')

A few questions:几个问题:

  1. I've seen the asterisk used inside the zip function to unpack tuples but have not seen it used to precede a function call like zip. I've seen the asterisk used inside the zip function to unpack tuples but have not seen it used to precede a function call like zip. What is the right way to understand the use of the asterisk in this manner?以这种方式理解星号使用的正确方法是什么?
  2. To try and understand what was happening, I looked at the results of print(*zip(X[j], X[i]) and it seems that the X & Y coordinates from each point are unpacked and zipped together such that there are two tuples. Why is that the right logic here? Also, what is the right way to understand how the plot function is handling/interpreting each pair of tuples? I've never seen a pair of tuples passed in such a way to the plot function.为了尝试了解发生了什么,我查看了print(*zip(X[j], X[i])的结果,似乎每个点的 X 和 Y 坐标都被解包并压缩在一起,这样有two tuples. Why is that the right logic here? Also, what is the right way to understand how the plot function is handling/interpreting each pair of tuples? I've never seen a pair of tuples passed in such a way to the plot function。

Consider two points, a and b .考虑两点, ab

a = [1,2]
b = [3,4]

When we zip them we get:当我们 zip 他们得到:

print(list(zip(a, b))) # [[1,3], [2,4]]

We can see that the first element of each are paired together, and similarly for the second element of each.我们可以看到每个元素的第一个元素是配对在一起的,每个元素的第二个元素也是如此。 This is just how zip works;这就是 zip 的工作原理; I suspect this makes sense for you.我怀疑这对你有意义。 If those are (x,y) points, then we've just grouped the x's and y's together.如果这些是 (x,y) 点,那么我们只是将 x 和 y 分组在一起。

Now;现在; consider the signature of plt.plot(x, y, ...) .考虑plt.plot(x, y, ...)的签名。 It expects the first argument to be all the x's, and the second argument to be all the y's.它期望第一个参数是所有的 x,第二个参数是所有的 y。 Well, the zip just grouped those together for us!好吧,zip 只是为我们将它们组合在一起! We can use the * operator to spread those over the first two arguments.我们可以使用*运算符将它们分布在前两个 arguments 上。 Notice that these are equivalent operations:请注意,这些是等效的操作:

p = list(zip(a, b))
plt.plot(*p)
plt.plot(p[0], p[1])

Side note: to expand to more points we just add the extra points into the zip:旁注:要扩展更多点,我们只需将额外点添加到 zip 中:

a = [1, 2]
b = [3, 4]
c = [5, 6]
print(list(zip(a, b, c))) # [[1, 3, 5], [2, 4, 6]]
plt.plot(*zip(a, b, c)) # plots the 3 points

* inside a function call converts a list (or other iterable) into a *args kind of argument. *在 function 调用中将列表(或其他可迭代)转换为*args类型的参数。

zip with several lists iterates through them pairing up elements: zip有几个列表遍历它们配对元素:

In [1]: list(zip([1,2,3],[4,5,6]))
Out[1]: [(1, 4), (2, 5), (3, 6)]

If we define a list:如果我们定义一个列表:

In [2]: alist = [[1,2,3],[4,5,6]]
In [3]: list(zip(alist))
Out[3]: [([1, 2, 3],), ([4, 5, 6],)]

That zip didn't do much. zip并没有做太多。 But if we star it:但如果我们给它加星标:

In [4]: list(zip(*alist))
Out[4]: [(1, 4), (2, 5), (3, 6)]

Check the zip docs - see the *args :检查zip文档 - 请参阅*args

In [5]: zip?
Init signature: zip(self, /, *args, **kwargs)
Docstring:     
zip(*iterables) --> A zip object yielding tuples until an input is exhausted.

   >>> list(zip('abcdefg', range(3), range(4)))
   [('a', 0, 0), ('b', 1, 1), ('c', 2, 2)]

The zip object yields n-length tuples, where n is the number of iterables
passed as positional arguments to zip().  The i-th element in every tuple
comes from the i-th iterable argument to zip().  This continues until the
shortest argument is exhausted.
Type:           type
Subclasses:  

* could also be used with a function like def foo(arg1, arg2, arg3):... *也可以与 function 一起使用,例如def foo(arg1, arg2, arg3):...

In plt.plot(*zip(X[j], X[i]), color='black') , plot has signature like plot(x, y, kwargs) .plt.plot(*zip(X[j], X[i]), color='black')plot具有类似plot(x, y, kwargs)的签名。 I don't think this is any different from我不认为这与

plt.plot(X[j], X[i], color='black')

but I'd have to actually test some code.但我必须实际测试一些代码。

edit编辑

def foo(x,y):
    print(x,y)

In [11]: X = np.arange(10).reshape(5,2)
In [12]: foo(X[1],X[0])
[2 3] [0 1]
In [13]: foo(*zip(X[1],X[0]))
(2, 0) (3, 1)

list(*zip(...)) is a list version of a matrix transpose. list(*zip(...))是矩阵转置的列表版本。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM