numpy自我划分的意外行为

时间:2013-04-09 16:31:51

标签: python numpy division

def f(x):
    x=x/5.
    return x
def g(x):
    x/=5.
    return x

x_var = np.arange(5,dtype=np.double)
f(x_var)
print x_var
g(x_var)
print x_var

Output:
[ 0.  1.  2.  3.  4.]
[ 0.   0.2  0.4  0.6  0.8]

这种行为对我来说有点奇怪,我一直认为x / = 5。相当于x = x / 5。 。但显然g(x)函数不会使用/ =操作创建新引用。有人可以为此提供解释吗?

3 个答案:

答案 0 :(得分:5)

  

我一直认为x / = 5。相当于x = x / 5

除非该类重写__idiv__运算符,否则numpy.ndarray会执行此操作。 numpy.ndarray会覆盖它以就地修改数组,这很好,因为它可以避免在不需要复制时创建数组的新副本。正如您所猜测的那样,它也会覆盖__i*__运算符的其余部分。

答案 1 :(得分:3)

Python的就地操作符允许操作修改等式左边的对象,而不是创建一个新对象。您将看到与list和其他内置可变类型相同的行为:

x = []
y = x
x += [1]
print y   # prints [1] because x still refers to the same object as y
x = x + [2]
print x   # prints [1, 2] for obvious reasons
print y   # prints [1] again because x has been rebound to a new list
          # while y still refers to the original one

所以这是预期的行为。

当处理不可变类型时,当然会创建一个新对象,因为现有对象无法修改。

答案 2 :(得分:0)

  

我一直认为x / = 5。相当于x = x / 5。

不是。执行x=x/5.后,您实际上是在幕后执行两个单独的操作:

temporary = x/5.
x = temporary

而当您使用/=运算符时,您明确要求Python在适当的位置修改对象x,而不创建临时对象。如其他答案中所述,/运算符会调用对象的__div__方法(如果有),而/=会调用其__idiv__方法。

如果要修改的对象很大,则就地修改非常有用:无需创建一个大型临时对象。但是,如果你不小心,它会咬你。特别是,在没有警告的情况下让函数修改其输入参数通常并不是一个好主意......