提问人:Martinghoul 提问时间:8/22/2023 最后编辑:jaredMartinghoul 更新时间:8/31/2023 访问量:90
Numpy 评估顺序
Numpy evaluation order
问:
当我查看与 Numpy 索引如何工作相关的一些问题(有时是视图,有时是副本)时,我在 Numpy 文档中遇到了一个示例,这让我有点困惑。具体来说,可以在这里找到它。
很简单,我不明白以下片段的原因
import numpy as np
x = np.arange(2)
x[[0, 0]] += 1
print(x)
产生它所产生的结果。
我知道你得到你得到的原因是它似乎扩展到类似的东西,但我不明白为什么会这样(你可以测试一下,如果你对相关方法进行子类化和添加消息,就会发生这种情况)。x[[0, 0]] += 1
x.setitem(x.getitem([0, 0]).iadd(1))
ndarray
给定优先级规则,语句不是首先转换为 ,这意味着后续扩展应该看起来更像吗?我很理解这会很尴尬,但我并不真正理解产生允许修改原始数组的扩展的形式逻辑。x[[0, 0]] += 1
x[[0, 0]] = x[[0, 0]] + 1
x.getitem([0, 0]).setitem(x.getitem([0, 0]).iadd(1))
是否存在优先于订阅的隐式绑定?
我试过了
import numpy as np
class A(np.ndarray):
def __getitem__(self, *args, **kwargs):
print("getitem")
r = np.ndarray.__getitem__(self, *args, **kwargs)
return r
def __setitem__(self, *args, **kwargs):
print("setitem")
r = np.ndarray.__setitem__(self, *args, **kwargs)
return r
def __iadd__(self, *args, **kwargs):
print("iadd")
r = np.ndarray.__iadd__(self, *args, **kwargs)
return r
nd = np.arange(2)
x = nd.view(A)
x[[0, 0]] += 1
print(x)
答:
就我而言,更多的挖掘使它更加令人费解。
我使用 ast 来查看解释器对以下块做了什么:
import numpy as np
x = np.arange(2)
x[[0, 0]] += 1
完整输出为:
("Module(body=[Import(names=[alias(name='numpy', asname='np')]), "
"Assign(targets=[Name(id='x', ctx=Store())], "
"value=Call(func=Attribute(value=Name(id='np', ctx=Load()), attr='arange', "
'ctx=Load()), args=[Constant(value=2)], keywords=[])), '
"AugAssign(target=Subscript(value=Name(id='x', ctx=Load()), "
'slice=List(elts=[Constant(value=0), Constant(value=0)], ctx=Load()), '
'ctx=Store()), op=Add(), value=Constant(value=1))], type_ignores=[])')
显示 的扩展的行,尽我所能格式化,是:x[[0,0]] += 1
AugAssign(
target=Subscript(
value=Name(id='x', ctx=Load()),
slice=List(elts=[Constant(value=0), Constant(value=0)], ctx=Load()),
ctx=Store()
),
op=Add(),
value=Constant(value=1)
)
因此,基于此,AugAssign 的目标应该是 Subscript 操作的结果,那么它最终是如何实现的呢?这仍然没有意义......x.setitem(x.getitem([0, 0]).iadd(1))
评论
AugAssign
numpy
ufunc.at
The object x is loaded, then y is added to it, and the resulting object is stored back in the original place. The precise action performed on the two arguments depends on the type of x, and possibly of y.
type of x
+=
numpy
[0,0]
+=
for i in [0,0]: x[i]+=1
我想我终于有了充分的了解......
Numpy文档描述了高级索引如何创建副本而不是视图,它指的是在引用的上下文中使用表达式(即在右侧)的情况。正如此处特别提到的同一文档,x[[1, 2]]
"...在分配期间,没有视图或副本是 创建...”
x[[1, 2]]
虽然这有点有帮助,但没有给出推理。但是,可以在此处的基本赋值语句的 Python 参考文档中找到它。文档中描述的订阅和切片的特定逻辑解释了为什么在分配目标(位于左侧)时没有创建副本。x[[1, 2]]
评论
__setitem___
get
set
set
get