[英]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:几个问题:
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
.考虑两点, a
和b
。
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.但我必须实际测试一些代码。
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.