2

I'm trying to create an object with a bunch of dictionaries (example below):

class test(object):
    def __init__(self):
       self.test_dict1 = {}
       self.test_dict2 = {}
       ...

I need to run a bunch of what-if scenarios that involve modifying those dictionaries and computing something based on them.

a = test()
for i in range(1000):
   b = copy.deepcopy(a)

   # do stuff to b and output result
   ...

However, most of the dictionary content will stay the same. I could just use copy.deepcopy() but that is very slow because it has to make a copy of ALL of the dictionary content (it is very large), and b will not b very different a, so it would make sense to reference a for the most part, and only override the keys for the items that are modified in b.

Since the dictionaries don't contain any mutable elements (i.e. all integers or strings), using copy.copy() on each individual dictionary should still work and will be significantly faster. However, since a is a class object, this code will also modify a:

# This code will modify a whenever b is modified
a = test()
for i in range(1000):
    b = copy.copy(a)

    # do stuff
    ...

How can I overload the __deepcopy__ function so that it only makes regular copies of objects? Also, as long as all of the dictionaries have immutable elements, am I correct in assuming this will work as intended (or is this not a good idea)?

ecksc
  • 148
  • 2
  • 9
  • I guess I should add I've read the post [here](http://stackoverflow.com/questions/1500718/what-is-the-right-way-to-override-the-copy-deepcopy-operations-on-an-object-in-p), but I don't really understand how to make it do what I want. I was thinking of using something like `return test(copy.copy(dict1), copy.copy(dict2))` and modifying the constructor for `test()` to include arguments, but that didn't work. – ecksc Dec 08 '14 at 05:08
  • I guess I could do something similar to the above and use `b = test(copy.copy(a.test_dict1),copy.copy(a.test_dict2), ...)`, but that syntax seems rather cumbersome. – ecksc Dec 08 '14 at 05:15
  • 1
    I would use a different approach which makes use of ``collections.ChainMap``. That way you can cheeply query each and every whatif scenario you want. – randomusername Dec 08 '14 at 17:22
  • Why not something like: `b = dict(**a)`? Are you sure that doesn't work for your needs? – Patrick Collins Dec 08 '14 at 17:46
  • randomusername: I'll look into that; I'm not familiar with it. – ecksc Dec 08 '14 at 17:50
  • Patrick: Since `a` and `b` are class objects and have methods associated with them, I'd really like to be able to copy them and be able to use them as one item, rather than individually copying the dictionaries and making them global properties of the project. I think that command would just copy the dictionary, not the class object. – ecksc Dec 08 '14 at 17:51
  • @randomusername: It looks like `ChainMap` would work, but unless I'm missing something, I still think I'd need to do some kind of override using for copy/deepcopy in order for it to work on a class object. EDIT: Also, I'm using Python 2.7...not that I couldn't upgrade to the latest version. – ecksc Dec 08 '14 at 18:10

1 Answers1

0

Since nobody else has ventured a solution to this, I'll post my own solution. I ended up modifying the constructor for the test class so that it could take in arguments and then passing the shallow copies of the dictionaries, like so:

import copy

class test(object):
    def __init__(self, test_dict1 = {}, test_dict2 = {}):
       self.test_dict1 = test_dict1
       self.test_dict2 = test_dict2
    ...

a = test()

# Set up initial values for a
...

for i in range(1000):
    b = test(copy.copy(a.test_dict1), copy.copy(a.test_dict2)

    # do stuff
    ...
ecksc
  • 148
  • 2
  • 9