strange side effect with lists!?
Bengt Richter
bokr at oz.net
Wed Oct 13 08:57:34 EDT 2004
More information about the Python-list mailing list
Wed Oct 13 08:57:34 EDT 2004
- Previous message (by thread): threads and sockets
- Next message (by thread): strange side effect with lists!?
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
On Wed, 13 Oct 2004 14:19:56 +0200, aleaxit at yahoo.com (Alex Martelli) wrote: ><Wolfgang.Stoecher at profactor.at> wrote: > >> Hello, >> >> I'm new to Python and playing around. I'm confused by the following >> behaviour: >> >> >>> l1 = [1] # define list >> >>> l2 = l1 # copy of l1 ? >> >>> l2,l1 >> ([1], [1]) >> >>> l2.extend(l1) # only l2 should be altered !? >> >>> l2,l1 >> ([1, 1], [1, 1]) # but also l1 is altered! >> >> So what is the policy of assignment? When is a copy of an object created? >> Where to find dox on this? > >Bruno's answer seems very thorough so I'll just try to briefly summarize >the answers: > >1. simple assignment (to a bare name, at least), per se, never > implicitly copies objects, but rather it sets a reference to an > object (_another_ reference if the object already had some). > >2. a new object is created when you request such creation or perform > operations that require it. Lists are particularly rich in such > operations (see later). Simple assignment to a bare name is not > an operation, per se -- it only affects the name, by making it refer > to whatever object (new, or used;-) is on the righht of the '='. > >3. I believe any decent book on Python will cover this in detail. > >Now for ways to have a new list object L2 made, with just the same items >and in the same order as another list object L1 ("shallow copy"): > >a. import copy; L2 = copy.copy(L1) > >This works to shallow-copy _any_ copyable object L1; unfortunately you >do have to import copy first. Module copy also exposes function >deepcopy, for those rare cases in which you wish to recursively also get >copies of all objects to which a "root object" refers (as items, or >attributes; there are some anomalies, e.g., copy.deepcopy(X) is X when X >is a class, or type...). > >b. L2 = list(L1) > >I find this is most often what I use - it works (making a new list >object) whatever kind of sequence, iterator, or other iterable L1 may >be. It is also what I recommend you use unless you have some very >specific need best met otherwise. > >c. various operations such as...: > L2 = L1 * 1 > L2 = L1 + [] > L2 = L1[:] >i.e. "multiply by one", "concatenate the empty list", or "get a slice of >all items". I'm not sure why, but the latter seems to be very popular, >even though it's neither as concise as L1*1 nor as clear and readable as >list(L1). > I got curious: >>> L = range(5) >>> L [0, 1, 2, 3, 4] Make it self-referential: >>> L[2]=L >>> L [0, 1, [...], 3, 4] >>> import copy >>> Lc = copy.copy(L) >>> Lc [0, 1, [0, 1, [...], 3, 4], 3, 4] >>> Ldc = copy.deepcopy(L) >>> Ldc [0, 1, [...], 3, 4] Interesting that the deep copy made the copy self-referential (i.e., to the copy itself) like the original's reference to its (different) self: >>> id(Ldc) == id(Ldc[2]) True Unlike the shallow copy: >>> id(Lc) == id(Lc[2]) False ...whose middle reference was merely copied and sill refers to L: >>> id(Lc[2]) == id(L) True But like the original: >>> id(L) == id(L[2]) True I'm impressed ;-) Regards, Bengt Richter
- Previous message (by thread): threads and sockets
- Next message (by thread): strange side effect with lists!?
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
More information about the Python-list mailing list