For instance if I have a dict of dicts or a dict of arrays but I only wish to "deep" copy to a depth of two levels is there an easy way to do this?
I was looking around to see if there was a library I could use or an example but I couldn't find anything. I am fairly new to Python or else I would write the subroutine to do this myself. Any ideas? Code snippets would be appreciated as it would be quicker for me to understand than just an explanation of how to do it.
Thanks.
ADDITIONAL INFO:
Some have ask why I would want to do this, I need a copy (not a ref as I am going to modify some of the values and I do not want the original modified) of some of the items from a dict but the dict is HUGE (many dict of dicts) and so I do not want to blow up my memory footprint
MY CODE SO FAR
Okay, I give up. This was more difficult than I expected and I don't have time to figure it out. My latest attempt with some debug/test code.
# Deep copy any iteratable item to a max depth and defaults to removing the
# rest. If you want to keep the stuff past max depth as references to orig
# pass the argument else_ref=1. Ex:
# dict_copy = copy_to_depth( dict_orig, 2, else_ref=1 )
def copy_to_depth( orig, depth, **kwargs):
copy = type(orig)()
for key in orig:
# Cannot find a reliable and consistent way to determine if the item
# is iterable.
#print orig[key].__class__
#if hasattr(orig[key], '__iter__'):
#if hasattr(orig[key], '__contains__'):
#if iterable( orig[key] ):
#try:
if hasattr(orig[key], '__contains__'):
if depth > 0:
copy[key] = copy_to_depth(orig[key], depth - 1, **kwargs)
else:
if 'else_ref' in kwargs:
copy[key] = orig[key]
else:
copy[key] = 'PAST_MAX_DPETH_ITERABLE_REMOVED'
#except:
else:
copy[key] = orig[key]
return copy
def iterable(a):
try:
(x for x in a)
return True
except TypeError:
return False
people = {'rebecca': 34, 'dave': 'NA', 'john': 18, 'arr': [9,8,{'a':1,'b':[1,2]}], 'lvl1':
{'arr': [9,8,{'a':1,'b':[1,2]}], 'dave': 'NA', 'john': 18, 'rebecca': 34, 'lvl2':
{'arr': [9,8,{'a':1,'b':[1,2]}], 'dave': 'NA', 'john': 18, 'rebecca': 34, 'lvl3':
{'rebecca': 34, 'dave': 'NA', 'john': 18, 'arr': [9,8,{'a':1,'b':[1,2]}]}}}}
print people
ppl_cpy = copy_to_depth(people, 1)
ppl_cpy['arr'][1] = 'nine' # does not mod orig
ppl_cpy['john'] = 0 # does not mod orig
ppl_cpy['lvl1']['john'] = 1 # does not mod orig b/c copy_to_depth
ppl_cpy['arr'][3]['a'] = 'aie' # does not mod orig
#ppl_cpy['lvl1']['lvl2']['john'] = 2 # Rest cause an error
#ppl_cpy['lvl1']['lvl2']['lvl3']['john'] = 3
print people
print ppl_cpy
ppl_cpy = copy_to_depth(people, 1, else_ref=1)
ppl_cpy['john'] = 0 # does not mod orig
ppl_cpy['lvl1']['john'] = 1 # does not mod orig b/c copy_to_depth was 1
ppl_cpy['lvl1']['lvl2']['john'] = 2 # Rest Do not cause error but modifies orig
ppl_cpy['lvl1']['lvl2']['lvl3']['john'] = 3
print people
print ppl_cpy
I Cannot find a reliable and consistent way to determine if the item is iterable. I have been reading through this post and trying to figure it out but it none of the solutions seemed to work for my test case.
I will just deep copy the entire dict and try to optimize the solution later (or not).
Thanks...