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)函数不会使用/ =操作创建新引用。有人可以为此提供解释吗?
答案 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__
方法。
如果要修改的对象很大,则就地修改非常有用:无需创建一个大型临时对象。但是,如果你不小心,它会咬你。特别是,在没有警告的情况下让函数修改其输入参数通常并不是一个好主意......