In python, how would I make a deep copy of a dict to a specific depth?

For example, if I have dict dicts or dict arrays, but I only want a “deep” copy to a depth of two levels, is there an easy way to do this?

I searched to see if there is a library that I could use, or an example, but I could not find anything. I am new to Python, otherwise I would write a routine to do it myself. Any ideas? The code snippets will be appreciated, as it would be easier for me to understand than just explaining how to do this.

Thank.

ADDITIONAL INFORMATION:

Some ask why I would like to do this, I need a copy (not a link, because I am going to change some values, and I do not want the original to be changed) of some elements from the dict, but the dictation is HUGE (many recorders), and therefore I don't want to blow my memory trail

MY CODE SO FAR

OK, I give up. It was harder than I expected, and I don’t have time to figure it out. My last 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 an element is iterable. I am reading this post and trying to figure it out, but none of the solutions seem to work for my test case.

I will just completely copy the entire dict file and try to optimize the solution later (or not).

Thank...

+5
source share
2

"plz, "...

, . :

def copy_to_depth(original, depth)
    copy = type(original)()
    for item in original
        if item is iterable and depth > 0
            copy + copy_to_depth(item, depth - 1)
        else
            copy + item
    return copy
+3

, , , , , . :

def copy_to_depth(original, depth)
    copy = type(original)()
    for item in original
        if item is iterable
            if depth > 0
                copy + copy_to_depth(item, depth - 1)
        else
            copy + item
    return copy

. ( , )

+1

All Articles