Maintaining a list

T

Thomas Philips

I'm teaching myself programming using Python and want to build a list
inside a function (rather like using a static variable in a Fortran
subroutime - the list must not disappear as soon as the subroutine is
exited). What's the simplest way to do this?

I'd like to write something of the form
def myroutine(x)
mylist = mylist.append(x)
print mylist
.
.
return

I'd like to call myroutine over and over again from a main program,
and want it to display the following behavior

1. The first time myroutine is called
myroutine("Item 1")
["Item 1"]

2. The second time myroutine is called
myroutine("Item 2")
["Item 1", "Item 2"]

3. The third time myroutine is called
myroutine("Item 3")
["Item 1", "Item 2", "Item 3"]

etc. etc.

The list must be initialized to an empty list before the first call,
and must be preserved between calls. I have not got to object oriented
programming as yet, so please keep the solution simple.

Sincerely

Thomas Philips
 
P

Peter Otten

Thomas said:
I'm teaching myself programming using Python and want to build a list
inside a function (rather like using a static variable in a Fortran
subroutime - the list must not disappear as soon as the subroutine is
exited). What's the simplest way to do this?

I'd like to write something of the form
def myroutine(x)
mylist = mylist.append(x)

append() returns None
print mylist
.
.
return

I'd like to call myroutine over and over again from a main program,
and want it to display the following behavior

1. The first time myroutine is called
myroutine("Item 1")
["Item 1"]

2. The second time myroutine is called
myroutine("Item 2")
["Item 1", "Item 2"]

3. The third time myroutine is called
myroutine("Item 3")
["Item 1", "Item 2", "Item 3"]

etc. etc.

The list must be initialized to an empty list before the first call,
and must be preserved between calls. I have not got to object oriented
programming as yet, so please keep the solution simple.

Sincerely

Thomas Philips

You're lucky, what you desired as a feature is a common pitfall: default
parameters are only initialized once:
.... lst.append(item)
.... return lst
....
myroutine("item1") ['item1']
myroutine("item2") ['item1', 'item2']
myroutine("item3") ['item1', 'item2', 'item3']
myroutine("item4")[:] = []
myroutine("item5") ['item5']
myroutine("item6")
['item5', 'item6']

This is just a rare case where you can use a mutable object as a default
argument. When you don't want to provide the possibility to change the list
from outside the function, just return a copy of it:
.... lst.append(item)
.... return lst[:]

Peter
 
K

Karl =?iso-8859-1?q?Pfl=E4sterer?=

subroutime - the list must not disappear as soon as the subroutine is
exited). What's the simplest way to do this?
I'd like to write something of the form
def myroutine(x)
mylist = mylist.append(x)
print mylist
.
.
return
I'd like to call myroutine over and over again from a main program,
and want it to display the following behavior
1. The first time myroutine is called
myroutine("Item 1")
["Item 1"]
2. The second time myroutine is called
myroutine("Item 2")
["Item 1", "Item 2"] [...]
The list must be initialized to an empty list before the first call,
and must be preserved between calls. I have not got to object oriented
programming as yet, so please keep the solution simple.

So if you don't want to use a class and not a global var create a
closure or use the feature that an optional argument gets evaluated an
bound the time the function is defined.

So if you write:
myfunc(1) [1]
myfunc(2) [1, 2]
myfunc(3)
[1, 2, 3]

always the list which had been created when the function was defined
gets used. You see that if you change the definition a bit.
.... lst.append(item)
.... print id(lst)
.... return lst
....
10484012
[1]
10484012
[1, 2].... myfunc(1, [])
10485068
[1]10484012
[1, 2, 3]


That may be what you want.

Another option is a closure.
.... lst = []
.... def func (item, lst = lst):
.... lst.append(item)
.... return lst
.... return func
....
myfunc = make_func()
myfunc(1) [1]
myfunc(2) [1, 2]



KP
 
J

Josiah Carlson

Thomas said:
I'm teaching myself programming using Python and want to build a list
inside a function (rather like using a static variable in a Fortran
subroutime - the list must not disappear as soon as the subroutine is
exited). What's the simplest way to do this? [snip]
The list must be initialized to an empty list before the first call,
and must be preserved between calls. I have not got to object oriented
programming as yet, so please keep the solution simple.

Work your way through these interactions.
>>> def myrutine(x, mylist=[]):
.... mylist.append(x)
.... print mylist
....
>>> myrutine(1) [1]
>>> myrutine(2) [1, 2]
>>> myrutine(10) [1, 2, 10]
>>> b = []
>>> myrutine(1, b) [1]
>>> b [1]
>>> myrutine(8) [1, 2, 10, 8]
>>> b [1]
>>>

One thing you need to remember is that list.append() returns None, not a
new list.

- Josiah
 
A

Aahz

The list must be initialized to an empty list before the first call,
and must be preserved between calls. I have not got to object oriented
programming as yet, so please keep the solution simple.

Unfortunately, while the other solutions given fit your technical
requirements, they're also what I (and probably others) would consider
unnatural for Python programs. That's partly because abuse of default
parameters and closures are actually two of the more difficult concepts
for people to learn correctly, IME. Here's a "less-simple" solution that
does what you want in a Pythonic fashion, though it still uses a trick:
.... def __init__(self):
.... self.data = []
.... def __call__(self, x):
.... self.data.append(x)
.... return self.data
....
myroutine = CallableList()
myroutine('1') ['1']
myroutine('spam') ['1', 'spam']
myroutine.data
['1', 'spam']
 
S

Steve

Thomas said:
I'm teaching myself programming using Python and want to build a list
inside a function (rather like using a static variable in a Fortran
subroutime - the list must not disappear as soon as the subroutine is
exited). What's the simplest way to do this? [snip]
The list must be initialized to an empty list before the first call,
and must be preserved between calls. I have not got to object oriented
programming as yet, so please keep the solution simple.

How about using a global variable? Define a variable in
your main program:

mylist = []

def myroutine(x)
global mylist
mylist.append(x)
print mylist
return None

Then call it like this:
>>> myroutine(1) [1]
>>> myroutine(2)
[1, 2]

and so forth.


There are disadvantages to using global variables, but
if you are looking for simplicity this is pretty simple.
 
T

Terry Reedy

Steve said:
How about using a global variable? Define a variable in
your main program:

mylist = []

def myroutine(x)
global mylist

Stylistic note:
Since the global name mylist is not rebound, this declaration is not
needed.
Since the global name mylist must not be rebound to meet its purpose,
I think the declaration positively should not be present, so it cannot be
rebound,
even by accident. Documenting the read-only use of a global with a comment
(especially in a much longer function) is a different matter, as with
# global mylist
mylist.append(x)

This mutates the object bound to 'mylist' without changing the binding.
print mylist
return None

Terry J. Reedy
 
S

Scott David Daniels

Steve said:
Thomas said:
I'm teaching myself programming using Python and want to build a list
inside a function (rather like using a static variable in a Fortran
subroutime - the list must not disappear as soon as the subroutine is
exited). What's the simplest way to do this?
...
mylist = []

def myroutine(x)
global mylist
mylist.append(x)
print mylist
return None

For the shortest (not simplest conceptually, but good to learn why it
works) solution, I'd propose:

mylist = []
myroutine = mylist.append
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,183
Messages
2,570,968
Members
47,518
Latest member
TobiasAxf

Latest Threads

Top