Python 为什么“/=”在只读numpy数组中会引发错误,而不是“x=x/y”?

Python 为什么“/=”在只读numpy数组中会引发错误,而不是“x=x/y”?,python,numpy,Python,Numpy,我一直认为x/=y等于x=x/y。但现在我面临的情况是,当我使用/=时会出现错误,但当使用x=x/y时不会出现错误。因此,它们在python中肯定不应该相同 代码是这样的。(是Tensorflow中的一个简单的深度学习代码,请阅读代码注释以了解一些详细信息 ValueError回溯(最近一次调用) 在() 1. ---->2列/1列 ValueError:输出数组为只读 我想问一下他们之间的区别。为什么我从/=中得到这个错误?如中所示,numpy数组可以显式标记为只读 当您运行somearra

我一直认为
x/=y
等于
x=x/y
。但现在我面临的情况是,当我使用
/=
时会出现错误,但当使用
x=x/y
时不会出现错误。因此,它们在python中肯定不应该相同

代码是这样的。(是Tensorflow中的一个简单的深度学习代码,请阅读代码注释以了解一些详细信息

ValueError回溯(最近一次调用)
在()
1.
---->2列/1列
ValueError:输出数组为只读
我想问一下他们之间的区别。为什么我从
/=
中得到这个错误?

如中所示,numpy数组可以显式标记为只读

当您运行
somearray=/value
时,您要求修改该数组,其方式(对于典型的可变对象,像大多数numpy数组一样)不仅改变单个引用,而且改变对象本身;这意味着
somearray
的所有副本(包括提供该副本的tensorflow库内部的副本)都会发生更改

相反,当运行
somearray=somearray/value
时,您正在创建一个新对象,而不是修改旧对象,因此与
somearray
标记为只读没有冲突


使用中的
\uu itruediv\uu
实现可以返回一个全新的对象,而不是修改只读数组,从而使只读数组上的
=/
+=
处理整数的方式相同;然而,这将意味着让操作分配内存——可能很昂贵;对于numpy来说,除非作者知道正在做昂贵的事情,否则不做这些事情是有意义的,这样人们就不会错误地编写不必要的慢代码。(让只读标志显著改变对象的性能和内存使用特性将是开发人员编写正确代码所需的额外状态!)

这与python操作符语义和最小意外原则有关

  • 表达式
    x=x+1
    大致相当于
    x=type(x)。\uuuuu add\uuuuuuux(x,1)
  • 表达式
    x+=1
    大致相当于
    x=type(x)。\uuuu iadd\uuuuuuux(x,1)
按照惯例,
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
从不改变调用它的对象<代码>\uuuu iadd\uuuu有时做,有时不做。Python的内置程序中有两个示例:

  • int
    str
    是不可变的,因此始终返回一个新对象。在这种情况下,重新分配步骤非常重要,因为否则名称将不会绑定到新值
  • 列表
    添加到位。在这种情况下,重新分配实际上是不可行的(但这种情况仍然存在)
Numpy数组通常是可变的。像
+=
-=
*=
/=
等操作都真正到位了。事实上,它们由支持常规操作(
add
subtract
multiply
true\u divide
)的相同UFUNC支持,使用
out
参数


开发人员可以选择只读数组:要么更改
\uuuu iadd\uuu
的语义,要么引发错误。最小惊奇原则规定了后者:函数在某些情况下不应在不通知您的情况下更改其基本行为。可以安全地假设您使用了
\uuuu iadd\uuuu
而不是
\uuuu add\uuuuu
,因为您需要就地操作。当函数无法执行此操作时,它会通知您,因为替代方法是执行您没有明确要求的操作。

什么错误?堆栈跟踪。通常情况下,错误消息是用来说明问题的。
/=
正在尝试进行就地更改,这只适用于可变值
x_train=x_train/1
正在变量中放置对不同不可变值的引用。所以,正如疯狂物理学家所说——错误信息本身很好地告诉了你问题到底是什么。为什么会有numpy标签?“你不是在使用tf吗?”MadPhysicast tf使用NumPy,x_列是一个NumPy阵列。有趣的事实是:对
x=x/1
的结果调用
x/=1
可能会很好。
import tensorflow as tf
(x_train, y_train), (x_test, y_test) = tf.keras.datasets.fashion_mnist.load_data()

# x_train is a (60000, 28, 28) numpy matrix

x_train /= 1 # this will raise error "ValueError: output array is read-only"
x_train = x_train / 1 # but this will work fine
ValueError                                Traceback (most recent call last)
<ipython-input-44-fceb080f135a> in <module>()
      1 
----> 2 x_train /= 1

ValueError: output array is read-only