-1

I've been trying to copy a 3D array but it seems like no matter what I do; amending the copy, amends the original as well.

I've tried multiple veriants of the top advice given on this question.

Can anyone explain to me why this code is amending the Clients array, after it's been copied and how to avoid this?

##### This block is to get and save the information

import csv

import datetime

import glob
import os

#import copy

from datetime import timedelta

list_of_files = glob.glob(r'U:\UEL\Sales and Marketing\Relationship - Sales\Team\Edinburgh Clients\Portal backups\Full export archive\*.csv') # * means all if need specific format then *.csv
latest_file = max(list_of_files, key=os.path.getctime)

with open(latest_file, newline='') as csvfile:
    data = list(csv.reader(csvfile))
    Vheaders = data[0]
    data.pop(0)

Clients = list(set(list(zip(*data))[9]))

i = 0
for line in Clients:
    Clients[i] = [Clients[i]]
    i = i + 1

Voids = []
CoTs = []

for row in Clients:
    Voids.append(row)

for row in Clients:
    CoTs.append(row)

#Voids = list(Clients) #This creates an array of arrays, an array of voids for each client

#CoTs = list(Voids) #Same as above for CoTs

#import pdb
#pdb.set_trace()


i = 0

for row in Clients:
    for line in data:
        #if line[0] == '443179':
            #import pdb
            #pdb.set_trace()
        if (datetime.date.today() - timedelta(days=7)) <= datetime.datetime.strptime(line[2], "%d/%m/%Y").date() < datetime.date.today(): 
            if line[9] == row[0]:
                Voids[i].append(line)
            else:
                pass
        else:
            pass
    i = i + 1
juanpa.arrivillaga
  • 88,713
  • 10
  • 131
  • 172
  • You are likely using a reference to a list rather than a unique list when building your "3D" list. I recommend reading https://nedbatchelder.com/text/names.html, then reexamining your code. – chepner Nov 18 '19 at 17:08
  • You are working with `list` objects, not arrays. In any case, for `Voids` and `Cots` are filled with the *same* list objects, the ones in `Clients`. So you can just do something like `Voids.append(row.copy())` and `CoTs.append(row.copy())` – juanpa.arrivillaga Nov 18 '19 at 17:12
  • You should look into `from copy import deepcopy`. – Error - Syntactical Remorse Nov 18 '19 at 17:12
  • Welcome to StackOverflow. See [minimal, reproducible example](https://stackoverflow.com/help/minimal-reproducible-example). We cannot effectively help you until you post your MRE code and accurately specify the problem. The amount of overhead in this posting detracts from our ability to read it. Please do not refer to arrays when you have only lists. `datetime` and `glob` are not part of the problem. Reduce this to the necessary code, show your problem clearly, and refer to the prior solutions. – Prune Nov 18 '19 at 17:22
  • Thanks very much @juanpa.arrivillaga! That worked! Can you tell me why Voids.append(row.copy()) works, when not using a loop and putting Voids = Clients.copy() doesn't? – James McIntyre Nov 18 '19 at 17:57
  • @JamesMcIntyre because, `.copy` is a shallow copy, it doesn't copy the elements *inside* the list, it only copies the list. So you create two distinct lists that happen to refer to the exact same objects. So you have to copy the elements *inside* `Clients` before adding them to another list, if you don't want them to share the same object – juanpa.arrivillaga Nov 18 '19 at 18:04
  • That's amazing, thanks very much @juanpa.arrivillaga! – James McIntyre Nov 18 '19 at 18:08

1 Answers1

0

You need a deepcopy. "Assignment statements in Python do not copy objects, they create bindings between a target and an object. For collections that are mutable or contain mutable items, a copy is sometimes needed so one can change one copy without changing the other."

Tweakimp
  • 393
  • 5
  • 16
  • Thanks very much Tweakimp, this works! import copy Voids = copy.deepcopy(Clients) @juanpa.arrivillaga's solution in the comments above also works: for row in Clients: Voids.append(row.copy()) – James McIntyre Nov 18 '19 at 18:05
  • I found this video helpful in understanding what happened here: https://www.youtube.com/watch?v=naG4uXpmVAU – James McIntyre Nov 18 '19 at 21:50