0

I come across some great questions and answers about copying lists by reference vs by value (this, this and this). Unfortunately, none of proposed solutions removes the reference from all the nested structures (tried b = a[:], b = list(a), copy.copy...). My last hope was copy.deepcopy but it doesn't work for nested structures when there is an array somewhere inside (I am working on openpyxl columns). I get this error on the bottom of the stack:

  File "C:\Python27\lib\copy.py", line 257, in _deepcopy_dict
    y[deepcopy(key, memo)] = deepcopy(value, memo)
TypeError: unhashable type: 'array.array'

My question is: is it possible to create a full copy of list a without any references, regardless of what is nested inside a?

Charlie Clark
  • 18,477
  • 4
  • 49
  • 55
Artur
  • 973
  • 1
  • 14
  • 29
  • 1
    Your error is not due to the `deepcopy`. Rather the fact that you are trying to use it as the `key` to a `dict`, which requires the `key` be a hashable type. – Cory Kramer Aug 02 '17 at 13:33
  • You call `copy.deepcopy` once on the entire structure and everything is copied recursively: `b = copy.deepcopy(a)` – cs95 Aug 02 '17 at 13:33
  • yet, the `copy.py` python module is the origin of the error. – Jean-François Fabre Aug 02 '17 at 13:35
  • I think I didn't understand you guys right. @CoryKramer, probably there is some dict inside this structure but why would it matter? @COLDSPEED this is what I did. In my case: `tmp_columns = deepcopy([r for r in ws.columns])` and it throws `TypeError`. – Artur Aug 02 '17 at 13:41
  • @Artur Just do `tmp_columns = deepcopy(ws.columns)`. – cs95 Aug 02 '17 at 13:41
  • ws.columns is a generator so I can't do it directly. If I split it to separate lines the result is the same (`tmp_columns = [r for r in ws.columns]` `tmp_columns_no_reference = deepcopy(tmp_columns)` also returns `TypeError`) – Artur Aug 02 '17 at 13:45

1 Answers1

1

Indeed, deepcopy is what you need. The issue is that the StyleArray class doesn't implement __deepcopy__.

The following fix seems to do the job:

def __deepcopy__(self, memo):
    return self.__copy__()

NB: the __copy__ is already a copy by value (to be checked).

It also answers your more generic question: in order to make a full copy of a nested structure, the non-standard nested elements must somehow indicate how to copy themselves.

YvesgereY
  • 3,778
  • 1
  • 20
  • 19
  • Thank you! For answer and explanation. Let me check this tommorow at work and I will mark it as answer after. – Artur Aug 02 '17 at 15:36
  • I looked deeper in `copy` module, and the docs say `This version does not copy types like module, class, function, method, nor stack trace, stack frame, nor file, socket, window, nor array, nor any similar types.` Is it the right way to modify array module with this deepcopy definition? – Artur Aug 16 '17 at 13:02
  • One good way to find out would be to test: clone, change the style (`StyleArray` state) in some way, and compare against original. My guess is that `copy` module doesn't copy arrays by default, since it might silently introduce memory and time penalties. Anyway it doesn't mean that's forbidden or "wrong" to do it. – YvesgereY Aug 16 '17 at 20:45