0

I tried this:

listing = []
entry = [0.0]*2   
entry[0] = 1.0
entry[1] = 2.0
listing.append(entry) # My first entry

entry[0] = 2.0
entry[1] = 3.0
listing.append(entry) # Another entry

The above does not work. The same entry pointer is retained, so updating the entry also updates the [1.0, 2.0] entry of the listing. I can get it to work with this:

entry[0] = 1.0
entry[1] = 2.0
listing.append(entry) # My first entry
entry = [0.0]*2

entry[0] = 2.0
entry[1] = 3.0
listing.append(entry) # Another entry
entry = [0.0]*2

But that seems clunky. Is there a cleaner way of doing this?

Update: (Which cuts through the chatter of the question this duplicates) The best way to do this, at least for Python 3.X users, is:

listing.append(entry.copy())
Jiminion
  • 5,080
  • 1
  • 31
  • 54
  • 4
    Read https://nedbatchelder.com/text/names.html. You are reusing the same list object `entry`, and `listing` only contains a *reference* to that list, not a copy of its values. – chepner May 17 '18 at 14:50
  • 1
    While adding to `listing` in your first code you can try appending `shallow copy` of `entry` by `listing.append(entry[:])` – niraj May 17 '18 at 14:51
  • @chepner, yes I figured that out. – Jiminion May 17 '18 at 14:54
  • Try to tell us what the purpose of you doing this is and I am certain we can come up with a "cleaner" way to do it all. – Anton vBR May 17 '18 at 14:55
  • 1
    The main reason it probably seems clunky is that you're thinking "What if I had to do this 15 times instead of just twice?" But if you had to do it 15 times, you'd only write it _one_ time; the only difference would be whether you put `entry = [0.0]*2` inside the loop (so every `entry` is different) or before the loop (so you append 15 of the same `entry`). – abarnert May 17 '18 at 14:56
  • @AntonvBR I am doing many calculations to create the entry values. Then I add them to a listing of indeterminate size. (They are points used to define a spline.) I am thinking since (somewhere) a new entry needs to be created, there is nothing 'wrong' with my working answer, but the shallow copy suggested by 0p3n5ourcE might be cleaner. – Jiminion May 17 '18 at 14:59
  • Best answer seems to be listing.append(entry.copy()), at least for Python 3.x. – Jiminion May 17 '18 at 15:13
  • 1
    Why is `entry` being reused in the first place? What context aren't you showing that makes `entry = [1.0, 2.0]; listing.append(entry); entry = [2.0, 3.0]; listing.append(entry)` *not* equivalent? – chepner May 17 '18 at 15:28
  • @chepner entry was being reused because I didn't understand that a copy was not being made. The context that (clumsily) fixed it was to reassign entry as [0.0]*2. This apparently overwrote the reference and created a new Python object. Due to reference counting, the old object still stayed alive in the 'listing' object. – Jiminion May 20 '18 at 19:03

2 Answers2

1

Assuming you want to keep entry as a list (for the purposes I suspect I recommend a namedtuple, though):

You can inline the entry creation

listing = []
listing.append([1.0,2.0])
listing.append([2.0,3.0])
bentheiii
  • 451
  • 3
  • 15
1

Instead of:

entry = [0.0]*2   
entry[0] = 1.0
entry[1] = 2.0

use:

# not mutable
entry = 1.0, 2.0
# mutable
entry = [1.0, 2.0]
ZZ ll
  • 176
  • 3