7
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) 函数不会使用 /= 操作创建新引用。任何人都可以为此提供解释吗?

4

3 回答 3

7

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

它是,除非类重写__idiv__操作符,就像这样numpy.ndarray做。 numpy.ndarray覆盖它以就地修改数组,这很好,因为它避免了在不需要复制时创建数组的新副本。您可以猜到,它还覆盖了其余的__i*__运算符。

于 2013-04-09T16:36:59.587 回答
3

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

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

所以这是预期的行为。

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

于 2013-04-09T16:47:38.997 回答
0

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

它不是。当你这样做时x=x/5.,你实际上是在后台执行两个单独的操作:

temporary = x/5.
x = temporary

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

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

于 2013-04-09T18:17:38.930 回答