Shallow or deep copy in a list comprehension
Hire the world's top talent on demand or became one of them at Toptal: https://topt.al/25cXVn
and get $2,000 discount on your first invoice
--------------------------------------------------
Music by Eric Matyas
https://www.soundimage.org
Track title: Dreamlands
--
Chapters
00:00 Shallow Or Deep Copy In A List Comprehension
01:01 Accepted Answer Score 8
02:04 Answer 2 Score 0
02:52 Thank you
--
Full question
https://stackoverflow.com/questions/2300...
--
Content licensed under CC BY-SA
https://meta.stackexchange.com/help/lice...
--
Tags
#python #list #python27 #listcomprehension
#avk47
ACCEPTED ANSWER
Score 8
You are creating a shallow, filtered copy.
Your loop doesn't create copies of member, it references them directly.
Not that you would need to create copies, all objects in your original list are immutable integers. Moreover, CPython interns small integers, creating copies would only result in the exact same objects being used for these.
To illustrate, try to create a copy of a list containing mutable objects instead. Here I used a dictionary:
>>> sample = [{'foo': 'bar'}]
>>> copy = [s for s in sample]
>>> copy[0]['spam'] = 'eggs'
>>> copy.append({'another': 'dictionary'})
>>> sample
[{'foo': 'bar', 'spam': 'eggs'}]
The copy list is a new list object containing a reference to the same dictionary contained in sample. Altering that dictionary is reflected in both copy and sample, but appending to copy doesn't alter the original list.
As for your updated loop code, your sample produces a New_List list that still shares objects, and New_List[3].visited is in fact True:
>>> New_List[3].ID
'8'
>>> New_List[3].visited
True
because it is still the same object found in Original at index 7:
>>> New_List[3] is Original[7]
True
which is the same object still found in ThirdList at index 2:
>>> ThirdList[2] is New_List[3]
True
ANSWER 2
Score 0
Another idea, which worked for me is to implement a flagClear method in the class
class CustomID (object):                   
    def __init__(self, *args):
        self.ID = ''
        self.manymore = float()
        self.visited = False
        self.isnoise = False
    def flagClear(self):
        self.visited = False
        return self
And then, every time I construct a new list, simply to use the method:
New_List = [member.flagClear() for member in Original if (int(member.ID)>4)]
If the only thing I modify in the CustomID is the .visited flag, than this works. Obviously, it will not be perfect. If someone needs a complete solution, the suggestion of Martijn Pieters will work best (implementing .copy() method):
import copy
class CustomID (object):                   
    def __init__(self, *args):
        self.ID = ''
        self.manymore = float()
        self.visited = False
        self.isnoise = False
    def CustomCopy(self):
        return copy.deepcopy(self)
New_List = [member.CustomCopy() for member in Original if (int(member.ID)>4)]
Thank you Martijn, this was really a learning experience for me.