Help - strange behaviour from python list

S

Sean Hammond

I've managed to create a scenario in which editing an object in a list of
objects seems to edit every object in the list, rather than just the one.
I'm totally stumped and wondered if anyone would be kind enough to read my
explanation and see if they have any suggestions. I have probably stumbled
into some typical newbie problem, but anyway:

I have two classes, Area and Agent:

class Agent:
def __init__(self,name):
self.name = name

class Area:
def __init__(self, occupants = []):
self.occupants = occupants

Now, I want to create a 'virtual environment' as a 2D list of Area
objects, so:

environment = []
for x in range(0,10):
environment.append([])
for y in range(0,10):
new_area = Area()
environment[-1].append(new_area)

This works fine, environment is now a 10*10 2D list of Area objects, and
the occupants member of each Area object is [].

Now, I want to add an occupants, in the form of an Agent object, to an
area in the environment:

new_agent = Agent("Bob")
environment[4][5].occupants.append(new_agent)

This is where it goes wrong, it looks as if new_agent gets appended to the
occupants list of EVERY Area object in environment. For example, the
following code:

for areas_list in environment:
for area in areas_list:
print len(area.occupants)

Will print out `1` 100 times over.

I must be making some really stupid mistake, but this just doesn't look
like the list behaviour I would expect. What's going on here?


--
 
?

=?ISO-8859-1?Q?Sch=FCle_Daniel?=

Sean said:
I've managed to create a scenario in which editing an object in a list
of objects seems to edit every object in the list, rather than just the
one. I'm totally stumped and wondered if anyone would be kind enough to
read my explanation and see if they have any suggestions. I have
probably stumbled into some typical newbie problem, but anyway:

just a hint
.... lst.append(val)
.... print lst
....
>>>
>>>
>>> foo(1) [1]
>>> foo(2) [1, 2]
>>> foo(3) [1, 2, 3]
>>> foo(4,[0]) [0, 4]
>>>

here list lst is created and bound once


compare with this one (which is what you really want)
.... if lst is None:
.... lst = []
.... lst.append(val)
.... print lst
....
>>> bar(1) [1]
>>> bar(2) [2]
>>> bar(3, [0]) [0, 3]
>>>

hth, Daniel
 
D

Duncan Booth

Sean said:
class Area:
def __init__(self, occupants = []):
self.occupants = occupants
....
I must be making some really stupid mistake, but this just doesn't
look like the list behaviour I would expect. What's going on here?

Whenever you use the default value for occupants in the constructor you
reuse the same list. Don't use mutable objects as default values:

def __init__(self, occupants=None):
if occupants is None:
self.occupants = []
else:
self.occupants = occupants
 
F

Fredrik Lundh

Sean said:
I've managed to create a scenario in which editing an object in a list of
objects seems to edit every object in the list, rather than just the one.
I'm totally stumped and wondered if anyone would be kind enough to read my
explanation and see if they have any suggestions. I have probably stumbled
into some typical newbie problem, but anyway:

some useful resources:

http://docs.python.org/tut/node6.html#SECTION006710000000000000000
(see the paragraph that starts with "important warning")

http://www.python.org/doc/faq/general/#why-are-default-values-shared-between-objects

http://docs.python.org/ref/function.html
(see the paragraph that starts with "Default parameters are evaluated when the
function definition is executed")

(you cannot say we didn't warn you ;-)

</F>
 
S

Sean Hammond

Right, thanks everyone, that's a useful lesson learned. As I suspected I
was being tripped over by some feature of Python I was unaware of. I had
been looking up lists in the documentation, not functions, and could find
no explanation.

Prbolem solved!

--
 

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

No members online now.

Forum statistics

Threads
473,745
Messages
2,569,487
Members
44,909
Latest member
DestinyKetoScam

Latest Threads

Top