Weird Python behaviour

J

Jonas Nilsson

Hello,

Lets say that I want to feed an optional list to class constructor:

class Family():
def __init__(self, fName, members = []):
self.fName = fName
self.members = members

Now, lets add members to two different instances of Family:

f1 = Family("Smith")
f1.members.append("Bill")

f2 = Family("Smithers")
f2.members.append("Joe")

Finally, lets look at the members in the Smithers family:

print f2.members
output: ['Bill', 'Joe']

Why on earth is the output ['Bill', 'Joe']!? Is there a simple
solution that separates f1 and f2 without forcing me to write code for
the special case when you don't feed members to the __init__()-function?

/Jonas
 
P

Peter Otten

Jonas said:
Lets say that I want to feed an optional list to class constructor:

class Family():
def __init__(self, fName, members = []):
Why on earth is the output ['Bill', 'Joe']!? Is there a simple
solution that separates f1 and f2 without forcing me to write code for
the special case when you don't feed members to the __init__()-function?

Congrats; you just encountered a very popular new trap ;) The most recent
explanation is only one day old:

http://mail.python.org/pipermail/python-list/2010-August/1252316.html

Peter
 
F

Francesco Bochicchio

Hello,

Lets say that I want to feed an optional list to class constructor:

class Family():
        def __init__(self, fName, members = []):
                self.fName = fName
                self.members = members

Now, lets add members to two different instances of Family:

f1 = Family("Smith")
f1.members.append("Bill")

f2 = Family("Smithers")
f2.members.append("Joe")

Finally, lets look at the members in the Smithers family:

print f2.members
output: ['Bill', 'Joe']

Why on earth is the output ['Bill', 'Joe']!? Is there a simple  
solution that separates f1 and f2 without forcing me to write code for  
the special case when you don't feed members to the __init__()-function?

/Jonas

You stumbled in two python common pitfalls at once :)
One, the default arguments issue, was already pointed to you.

The other one is that python variables are just names for objects.
Assigning a variable never mean making a copy, it just means using
another name for the same object.
There used to be a very nice (also graphic) explanationor this
somewhere on the web, but my googling skills failed me this time,
so instead I'll show you the concept using your own code:
.... def __init__(self, fName, members = []):
.... self.fname = fName
.... self.members = members
....
mlist = ["Bill"]
f1 = Family("Smiths", mlist )
mlist.append( "John" ) # attempt to not-so-clever reyse of the sme variable
f2 = Family("Smithers", mlist )
f1.members
['Bill', 'John']

Now my example is a bit contrieved but I'm sure you got the idea : in
your example is better to copy the list with
self.members = members[:].

Better yet, you could make use of python arguments grouping feature :.... def __init__(self, fName, *members ):
.... self.members = list(members) # because members is a
tuple
.... self.fname = fName
....
f1 = Family("Smith")
f1.members.append("Bill")
f2 = Family("Smithers")
f2.members.append("Joe")
f2.members ['Joe']
f1.members
['Bill']

This solves your "no initial member" special case and allows for an
easier syntax for creating class instances
(no brackets involved)
f3 = Family("Bochicchio", "Angelo", "Francesco", "Mario")
f3.members ['Angelo', 'Francesco', 'Mario']


Ciao
 
S

Stefan Schwarzer

Hi,

There used to be a very nice (also graphic) explanationor this
somewhere on the web, but my googling skills failed me this time,
so instead I'll show you the concept using your own code:

Probably this isn't the page you're referring to, but I only
recently gave a beginners' talk at EuroPython:

http://sschwarzer.com/download/robust_python_programs_europython2010.pdf

The topic of identity and assignments starts on slide 7,
nice graphics start on slide 10. ;-)

Stefan
 
F

Francesco Bochicchio

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,770
Messages
2,569,584
Members
45,078
Latest member
MakersCBDBlood

Latest Threads

Top