Re: [Tutor] how to *really* copy a list
John, Thanks. Your message was very helpful. I will tattoo it to my forehead. hehe... i notice that the learning python book also explains so of this and i shall study that as well cheers, kevin On Apr 27, 2006, at 10:14 PM, [EMAIL PROTECTED] wrote: On 28/04/06, kevin parks [EMAIL PROTECTED] wrote: In most case you are fine operating on the list in place and altering the existing list. In some cases you want your code to stop molesting your poor mutables and really honestly sincerly copy the dang thing. In this case i am making a function that does odd smmetry mirroring. But i want my orginal list to remain intact def mirror(seq): odd symmetry mirroring [1, 2, 3, 4] -- [1, 2, 3, 4, 3, 2, 1] foo=seq[:-1]# copy list, excluding last element for odd symetry foo.reverse() # flip it seq.extend(foo) return seq Hi Kevin, Your problem is this line: seq.extend(foo) ___ Tutor maillist - Tutor@python.org http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] how to *really* copy a list
Ed, I should have realized that the nesting would create the problem, but i didn't have that in mind... i always thought that the difference between extend and append was that extend did not yield a nested list. I really need to revisit this issue and get it right in my mind. It is a 'gotcha' that i remember reading about often but, now that it has bit me a few times hehe so much to know... -kevin-- On Apr 29, 2006, at 6:00 AM, [EMAIL PROTECTED] wrote: Hi Kevin, Your problem is this line: seq.extend(foo) This is the line that mutates your original list. There are a few ways you could procede here. One way is to make a copy of the argument, like this: def mirror(seq): start = list(seq) end = seq[:-1] end.reverse() start.extend(end) return start Notice that we've not calling any methods on seq, so seq won't be changed. The first line, start = list(seq), instructs python to build a new list out of the elements of seq. You could also write start = seq[:] here --- I'm not sure which is the preferred way. A little 'gotcha' with this is that if you have nested lists, these methods don't copy the nested lists, only the outer list (which makes sense, but can be surprising the first time you encounter it). If for some reason you want to copy nested lists, look into deepcopy(), otherwise you'll be fine. ___ Tutor maillist - Tutor@python.org http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] how to *really* copy a list
On 28/04/06, John Fouhy [EMAIL PROTECTED] wrote: On 28/04/06, kevin parks [EMAIL PROTECTED] wrote: In most case you are fine operating on the list in place and altering the existing list. In some cases you want your code to stop molesting your poor mutables and really honestly sincerly copy the dang thing. In this case i am making a function that does odd smmetry mirroring. But i want my orginal list to remain intact def mirror(seq): odd symmetry mirroring [1, 2, 3, 4] -- [1, 2, 3, 4, 3, 2, 1] foo=seq[:-1]# copy list, excluding last element for odd symetry foo.reverse() # flip it seq.extend(foo) return seq Hi Kevin, Your problem is this line: seq.extend(foo) This is the line that mutates your original list. There are a few ways you could procede here. One way is to make a copy of the argument, like this: def mirror(seq): start = list(seq) end = seq[:-1] end.reverse() start.extend(end) return start Notice that we've not calling any methods on seq, so seq won't be changed. The first line, start = list(seq), instructs python to build a new list out of the elements of seq. You could also write start = seq[:] here --- I'm not sure which is the preferred way. A little 'gotcha' with this is that if you have nested lists, these methods don't copy the nested lists, only the outer list (which makes sense, but can be surprising the first time you encounter it). If for some reason you want to copy nested lists, look into deepcopy(), otherwise you'll be fine. Also, personally I think list(seq) is better than seq[:] because it can cope with anything put into it that it could possibly work with (even dicts and iterators). def i(): ... for n in range(3): ... yield n ... list(i()) [0, 1, 2] d = {'a':1,'b':2} list(d) ['a', 'b'] i()[:] Traceback (most recent call last): File stdin, line 1, in ? TypeError: unsubscriptable object d[:] Traceback (most recent call last): File stdin, line 1, in ? TypeError: unhashable type Ed ___ Tutor maillist - Tutor@python.org http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] how to *really* copy a list
I know there is an answer to this somewhere. it is prolly the biggest stumbling block to all python n00bs, but it hasn't been an issue for me in a while. Suddenly i am getting bit by it and can't for the life of me keep straight the two way of opperating on lists. In most case you are fine operating on the list in place and altering the existing list. In some cases you want your code to stop molesting your poor mutables and really honestly sincerly copy the dang thing. In this case i am making a function that does odd smmetry mirroring. But i want my orginal list to remain intact a = [1, 2, 3, 4] mirror(a) [1, 2, 3, 4, 3, 2, 1] a [1, 2, 3, 4, 3, 2, 1] clearly this is not happening. believe it or not i googled around figuring the answer would be posted someplace... but if it is i haven't found it. Every thing i land on says copy a list by [:] slicing like i have below... how to i really (not kidding) copy a list? I swear i used to know this, but i haven't had to do it in a long long long time. # === dumb code: def mirror(seq): odd symmetry mirroring [1, 2, 3, 4] -- [1, 2, 3, 4, 3, 2, 1] foo=seq[:-1]# copy list, excluding last element for odd symetry foo.reverse() # flip it seq.extend(foo) return seq ___ Tutor maillist - Tutor@python.org http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] how to *really* copy a list
On 28/04/06, kevin parks [EMAIL PROTECTED] wrote: In most case you are fine operating on the list in place and altering the existing list. In some cases you want your code to stop molesting your poor mutables and really honestly sincerly copy the dang thing. In this case i am making a function that does odd smmetry mirroring. But i want my orginal list to remain intact def mirror(seq): odd symmetry mirroring [1, 2, 3, 4] -- [1, 2, 3, 4, 3, 2, 1] foo=seq[:-1]# copy list, excluding last element for odd symetry foo.reverse() # flip it seq.extend(foo) return seq Hi Kevin, Your problem is this line: seq.extend(foo) This is the line that mutates your original list. There are a few ways you could procede here. One way is to make a copy of the argument, like this: def mirror(seq): start = list(seq) end = seq[:-1] end.reverse() start.extend(end) return start Notice that we've not calling any methods on seq, so seq won't be changed. The first line, start = list(seq), instructs python to build a new list out of the elements of seq. You could also write start = seq[:] here --- I'm not sure which is the preferred way. Another option is to use arithmetic --- you can add lists together, and this creates a new list. eg: def mirror(seq): end = seq[:-1] end.reverse() return seq + end Finally, just a side comment: You can use slicing to reverse the end for you as well. So, we could rewrite the last function as: def mirror(seq): end = seq[-2::-1] return seq + end Which means there is a one-line version as well: def mirror(seq): return seq + seq[-2::-1] HTH! -- John. ___ Tutor maillist - Tutor@python.org http://mail.python.org/mailman/listinfo/tutor