Why aren't copy and deepcopy in __builtins__?

Steven D'Aprano steve+comp.lang.python at pearwood.info
Mon Mar 28 17:23:28 EDT 2011


On Mon, 28 Mar 2011 10:30:03 -0700, John Ladasky wrote:

> On Mar 28, 2:25 am, Andrea Crotti <andrea.crott... at gmail.com> wrote:
>> John Ladasky <lada... at my-deja.com> writes: I almost never use them
>> either, maybe also in many cases you could avoid using them...
>> When for example you use them?
> 
> 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.


-- 
Steven



More information about the Python-list mailing list