Re: How to append a modified list into a list?

2016-11-19 Thread jfong
Peter Otten at 2016/11/19 5:40:34PM wrote:
> And now for something completely different ;)
> 
> What if you only record the changes to the list? For a long list that would 
> save space at the expense of calculation time. For example:

Excellent! Although not 100% fit into my application, I must study how this 
Class works. Thank you.

--Jach
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: How to append a modified list into a list?

2016-11-19 Thread Peter Otten
jf...@ms4.hinet.net wrote:

> I have a working list 'tbl' and recording list 'm'. I want to append 'tbl'
> into 'm' each time when the 'tbl' was modified. I will record the change
> by append it through the function 'apl'.
> 
> For example:
> 
tbl=[0,0]
m=[]
> 
tbl[0]=1
apl(tbl)
m
> [[1,0]]
> 
tbl[1]=2
apl(tbl)
m
> [[1,0], [1,2]]
> 
> How to define this function properly?
> 
> Obviously the most intuitive way doesn't work.
> def apl0(tbl):
> m.append(tbl)
> 
> and introducing a local variable will not help either.
> def apl1(tbl):
> w=tbl
> m.append(w)
> 
> I figure out a workable way, but looks ugly.
> def apl2(tbl):
> w=[]
> w[:]=tbl
> m.append(w)
> 
> I know those binding tricks between names and objects. Just wondering if
> there is an elegant way of doing this:-)
> 
> --Jach

And now for something completely different ;)

What if you only record the changes to the list? For a long list that would 
save space at the expense of calculation time. For example:

$ cat list_history.py
import collections
from itertools import islice

class List(collections.Sequence):
def __init__(self, items):
self._items = list(items)
self._history = []
def __setitem__(self, index, value):
if isinstance(index, slice):
value = list(value)
old = self._items[index]
if len(old) != len(value):
raise ValueError("size changes not supported")
else:
old = self._items[index]
self._history.append((index, old))
self._items[index] = value
def __getitem__(self, index):
return self._items[index]
def __len__(self):
return len(self._items)
def __repr__(self):
return repr(self._items)
def historic_state(self, n):
items = self._items[:]
for index, value in islice(reversed(self._history), n):
items[index] = value
return items
def history_len(self):
return len(self._history) + 1

if __name__ == "__main__":
items = List("abcdefghijk")
print(items)
# apply some changes
items[3] = "foo"
items[7] = "bar"
items[3] = 42
items[3:6] = "xyz"
items[5:7] = (1, 2)
print(items)
# let's go back in time
for i in range(items.history_len()):
print("#{}: {}".format(i, items.historic_state(i)))
$ python3 list_history.py 
['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k']
['a', 'b', 'c', 'x', 'y', 1, 2, 'bar', 'i', 'j', 'k']
#0: ['a', 'b', 'c', 'x', 'y', 1, 2, 'bar', 'i', 'j', 'k']
#1: ['a', 'b', 'c', 'x', 'y', 'z', 'g', 'bar', 'i', 'j', 'k']
#2: ['a', 'b', 'c', 42, 'e', 'f', 'g', 'bar', 'i', 'j', 'k']
#3: ['a', 'b', 'c', 'foo', 'e', 'f', 'g', 'bar', 'i', 'j', 'k']
#4: ['a', 'b', 'c', 'foo', 'e', 'f', 'g', 'h', 'i', 'j', 'k']
#5: ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k']


-- 
https://mail.python.org/mailman/listinfo/python-list


Re: How to append a modified list into a list?

2016-11-18 Thread jfong
Oh, I don't know slice well enough:-(

So, slice tbl[:] will create a new object (a copy of tbl) which can be passed 
as a function argument
m.append(tbl[:])

or bind to a new name
w=tbl[:]

or re-bind to itself
w[:]=tbl

Thanks you, Ian and Steve.

Steve D'Aprano at 2016/11/19 11:01:26AM wrote:
> In newer versions of Python, you can do this:
> m.append(tbl.copy())

I like it:-)

--Jach

-- 
https://mail.python.org/mailman/listinfo/python-list


Re: How to append a modified list into a list?

2016-11-18 Thread Steve D'Aprano
On Sat, 19 Nov 2016 12:44 pm, jf...@ms4.hinet.net wrote:

> I have a working list 'tbl' and recording list 'm'. I want to append 'tbl'
> into 'm' each time when the 'tbl' was modified. I will record the change
> by append it through the function 'apl'.
[...]
> Obviously the most intuitive way doesn't work.
> def apl0(tbl):
> m.append(tbl)

That works perfectly -- it just doesn't do what you want.

It sounds like what you want is to append a COPY of the list rather than the
list itself. I'm not sure why, making copies of things in Python is usually
rare, but perhaps I don't understand what you are doing with this "working
list" and "recording list".

The simplest way to do this is:


m.append(tbl[:])  # use slicing to make a copy


In newer versions of Python, you can do this:


m.append(tbl.copy())


But that won't work in Python 2.7. Or you can do this:



from copy import copy
m.append(copy(tbl))



But the most Pythonic way (the most standard way) is to use a slice to copy
the list: m.append(tbl[:])

 
> and introducing a local variable will not help either.
> def apl1(tbl):
> w=tbl
> m.append(w)

Of course not. Assignment does not make a copy.





-- 
Steve
“Cheer up,” they said, “things could be worse.” So I cheered up, and sure
enough, things got worse.

-- 
https://mail.python.org/mailman/listinfo/python-list


Re: How to append a modified list into a list?

2016-11-18 Thread Ian Kelly
On Nov 18, 2016 6:47 PM,  wrote:

I have a working list 'tbl' and recording list 'm'. I want to append 'tbl'
into 'm' each time when the 'tbl' was modified. I will record the change by
append it through the function 'apl'.

For example:

>>>tbl=[0,0]
>>>m=[]

>>>tbl[0]=1
>>>apl(tbl)
>>>m
[[1,0]]

>>>tbl[1]=2
>>>apl(tbl)
>>>m
[[1,0], [1,2]]

How to define this function properly?

Obviously the most intuitive way doesn't work.
def apl0(tbl):
m.append(tbl)

and introducing a local variable will not help either.
def apl1(tbl):
w=tbl
m.append(w)

I figure out a workable way, but looks ugly.
def apl2(tbl):
w=[]
w[:]=tbl
m.append(w)

I know those binding tricks between names and objects. Just wondering if
there is an elegant way of doing this:-)


The important thing is to copy the list, not rebind it.

def apl(tbl):
m.append(tbl[:])

Or:

def apl(tbl):
m.append(list(tbl))
-- 
https://mail.python.org/mailman/listinfo/python-list