Reputation: 411
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]
This behavior is a little bit strange to me, I always thought x/=5. was equivalent to x=x/5. . But clearly the g(x) function does not create a new reference with /= operation. Could anyone offer an explanation for this?
Upvotes: 7
Views: 582
Reputation: 184345
Python's in-place operators allow the operation to modify the object on the left side of the equation rather than creating a new one. You'll see the same behavior with list
s and other built-in mutable types:
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
So this is expected behavior.
When dealing with immutable types, of course, a new object is created, because the existing one can't be modified.
Upvotes: 3
Reputation: 20349
I always thought x/=5. was equivalent to x=x/5.
It is not. When you do x=x/5.
, you're in fact performing two separate operations below the hood:
temporary = x/5.
x = temporary
whereas when you're using the /=
operator, you're explicitly asking Python to modify your object x
in place, without the creation of a temporary object. As mentioned in other answers, the /
operator calls the __div__
method of your object (if any), while /=
calls its __idiv__
method.
The in-place modification is quite useful if the object you're modifying is large: no need to create an as-large temporary object. However, it can bite you if you're not careful. In particular, it's usually not that great an idea to have a function modify its input parameters without warning...
Upvotes: 0
Reputation: 64348
I always thought x/=5. was equivalent to x=x/5
It is, unless the class overrides the __idiv__
operator, like numpy.ndarray
does.
numpy.ndarray
overrides it to modify the array in-place, which is good because it avoids creating a new copy of the array, when copying is not required. As you can guess, it also overrides the rest of the __i*__
operators.
Upvotes: 7