To take one example: neural network programming. I construct a network
object (which is quite complex), test it, and keep it. Next, I copy the
network object, apply a slight variation to it, and test that. If the
variant performs less well than the original, I discard the variant, and
try another slightly-varied copy of the original. If the variant is
superior, I discard the original. And so on.
Without knowing the details of your neural network code, it isn't clear
that *copying* is the right way to do this. Presumably you initialize
your network object with some set of input parameters, as in:
obj = neural_network(a, b, c, d, e, f)
Those input params are probably far less complex than the internal
details of the object, particularly after it is trained. It is probably
faster and simpler to create a new variant directly from the modified
parameters:
obj = neural_network(a, b, c, d+1, e, f) # (say)
but of course your mileage may vary.
Another use: When I'm profiling code for speed, I generate a sequence of
function calls in a specific order. I would like to retain that ordered
sequence for when I print out the results of my speed test, but also
generate shuffled variations of that sequence. But random.shuffle()
alters the sequence in place, it does not return a copy. If shuffle()
did return a copy, I would not need to invoke copy myself, but that's
how the library function is written.
Just make sure you're using a standard list (as opposed to some arbitrary
sequence), and then use string-slicing to make a copy:
func_calls = [a, b, c, d, e, f]
another = func_calls[:]
shuffle(another)
If the string-slicing notation is too mysteriously Perl-like for you, you
can write that line as:
another = list(func_calls)
There's usually no need for a deep copy, particularly if you're writing
code in a semi-functional style with a minimum of in-place modifications
-- a shallow copy will do.
I don't believe I have ever needed to use either copy.deepcopy or
copy.copy in production code. Normally techniques like list slicing, list
comprehensions, {}.copy() and similar are more than enough. It's nice to
have the copy module there as a fall-back if I should ever need it, but I
haven't needed it yet.