python - 在元组赋值(Python)中使用切片 Numpy 数组的机制是什么?
问题描述
我知道 Python 中的元组赋值如下
a, b = b, a
b
工作原理是先将and打包a
成一个元组(b, a)
,然后将其解包到a
and b
,从而实现在一个语句中交换两个名称。但我发现 ifa
和b
被切片的 Numpy 数组替换:
# intended to swap the two halves of a Numpy array
>>> import numpy as np
>>> a = np.random.randn(4)
>>> a
array([-0.58566624, 1.42857044, 0.53284964, -0.67801528])
>>> a[:2], a[2:] = a[2:], a[:2]
>>> a
array([ 0.53284964, -0.67801528, 0.53284964, -0.67801528])
我的猜测是,打包的元组(a[2:], a[:2])
实际上是一个指向a[2]
and的内存位置的“指针”元组a[0]
。解包时, firsta[:2]
被从内存开始的值覆盖a[2]
。然后a[2:]
被从 开始的值覆盖a[0]
。这是对机制的正确理解吗?
解决方案
所以,这不是简单的任务。名称-对象绑定语义适用于简单赋值,即a = b
.
如果你这样做:
a[ix] = b
然后将确切的行为推迟到类型,即,它等价于
type(a).__setitem__(a, ix, b)
Numpy 数组基本上是面向对象的原始类 C 数组的包装器,实现了“真正的”多维数组接口。在这种情况下,要理解的关键是不同的 numpy 数组对象可以共享底层缓冲区。简单切片总是创建一个 numpy.ndarray 对象,它是原始数组的视图。
所以在这种情况下,b
上面实际上是对nd.array.__getitem__
. 它返回一个视图。
因此,考虑 Python 列表的简单情况。右手边:
(a[2:], a[:2])
创建两个独立列表对象的元组(尽管是浅复制的)。
当它们被分配到左侧的分配目标序列时,突变没有任何共享效果。三个列表对象有三个独立的缓冲区(列表对象不会创建视图)。
另一方面,该表达式a[2:], a[:2]
创建一个元组,其切片原始 nd.array 对象的结果由 控制nd.array.__getitem__
。这会创建两个新的数组对象,但它们是原始数组中底层缓冲区的视图。基本上,您在三个不同的数组对象之间共享相同的底层可变原始缓冲区。
推荐阅读
- javascript - 链接未在 sharex 自定义上传器上发回
- linux - 我想以 6 秒的固定间隔打开多个 elink
- arrays - 合并分区/又名压缩算法
- javascript - 为每个用户只保留 100 条新记录,删除 firebase 中的旧记录
- node.js - passport-azure-ad 始终重定向到 failureRedirect 但未显示错误(nodejs)
- angular - 如何使用 Angular Routing 在 Angular 中管理多个文章帖子?
- docker - docker:拉取图像时出现“第一条记录看起来不像 TLS 握手”错误
- c - 可以使用 TensorFlow C API 训练 Keras 模型吗?
- ios - 加号或减号按钮值不会快速更新
- forms - VueJs 以表单形式提交多行数组