<Update: sorry, the following explanation is interesting, but missed the point of the question actually being asked. Be sure to also read my later reply below.>
The semantics of argument passing to functions in python can cause trouble if you’re not careful. Objects are passed “by reference” not “by value”. So if w_in is a numpy array, then what you are passing to the function is a reference to the global object. If you modify w_in within the function by using an “in place” operation like:
w_in -= ( ... some expression ...)
then you have modified the global value. That may or may not be a good thing, but that is a “side effect” of a function. Generally speaking, it’s always a better idea to make your functions “self-contained” meaning that they do not reference global variables even in “read-only” mode and to make sure that they don’t have side effects like modifying global objects, unless that is your explicit goal. What the “deepcopy” there does is make sure that you’ve created your own private copy of the object pointed to by w_in. The difference between simple copy and “deep” copy is that if the object itself contains object references, then you need the “deep” version. That is discussed more on the thread that I reference below. In the case of numpy arrays, the “deep” copy is not really necessary, but it doesn’t hurt to be on the safe side. If the object in question is a python dictionary containing numpy arrays, then the “deep” copy is definitely required. So maybe it’s better just to get in the habit of using deepcopy.
Here’s a thread from DLS which covers some examples like this. Make sure to also read this later post in that same thread which has another example of the nasty surprises you can get from python object references.