Blade
Blade

Reputation: 1110

Problem with variable assignment in python

I'm running the following code in python:

w= np.random.rand(3) 
w_old=np.zeros((3,))

while (np.linalg.norm(w - w_old)) / np.linalg.norm(w) > 1e-5:

    w_old=w

    print w
    print w_old

    w[0]-=eta*dE1i
    w[1]-=eta*dE2i
    w[2]-=eta*dE3i

    print w
    print w_old

The results for the prints are :

[ 0.22877423  0.59402658  0.16657174]

[ 0.22877423  0.59402658  0.16657174]

and

[ 0.21625852  0.5573612   0.123111  ]

[ 0.21625852  0.5573612   0.123111  ]

I'm wondering why the value of w_old has been changed? Shouldn't it be updated after going back to the beginning of the while loop? How can I fix this?

Upvotes: 1

Views: 154

Answers (3)

Blade
Blade

Reputation: 1110

Just to conclude the answers above, according to python documentation

Assignment statements in Python do not copy objects, they create bindings between a target and an object.

So, the solution is

For collections that are mutable or contain mutable items, a copy is sometimes needed so one can change one copy without changing the other.

So using copy() we can rewrite the code as

import numpy as np

w= np.random.rand(3)
w_old=np.zeros((3,))

while (np.linalg.norm(w - w_old)) / np.linalg.norm(w) > 1e-5:

    w_old=w.copy()

    print(w)
    print(w_old)

    w[0]-=0.01
    w[1]-=0.01
    w[2]-=0.01

    print(w)
    print(w_old)

and get

[0.79666571 0.82305671 0.41167625]
[0.79666571 0.82305671 0.41167625]

and

[0.78666571 0.81305671 0.40167625]
[0.79666571 0.82305671 0.41167625]

Upvotes: 0

chari Muvilla
chari Muvilla

Reputation: 69

Just to clear things up, variables are independent so:

a=5
b=a

will work just fine if you change either a or b. But lists and dictionaries cannot be copied the same way, so:

a=[1,2]
b=a
a[0]=100
print(b[0])

will give you 100 because now a and b are the same thing with two names. So as suggested before use

w_old = w.copy()

instead so w_old is a new list and not just another name for the old one.

Upvotes: 1

MSeifert
MSeifert

Reputation: 152795

Just using

w_old = w

doesn't copy w, using = just tells python that you want another name for whatever is stored in w. So every in-place change to w will also change w_old. There is a really nice blog post about it in case you want more details Ned Batchelder: "Facts and myths about Python names and values"

You can explicitly copy a numpy array, for example, using the copy method:

w_old = w.copy()

Upvotes: 2

Related Questions