Weird Python behaviour

Benjamin Kaplan benjamin.kaplan at case.edu
Tue Aug 10 10:43:22 EDT 2010


On Tue, Aug 10, 2010 at 4:58 AM, Jonas Nilsson <jmnc at spray.se> wrote:
> 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

In python, a function definition is an executable statement, not a
declaration. Default args only get evaluated once- when the function
is first created. You have to use a sentinel value and create the
object inside the function if you want it to get executed every time.


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

If None is a valid argument to this function, then make a dummy object
and check identity (to make sure it's *that* object and not just
something that evaluates equal).

sentinel = object()
def something_that_accepts_none(foo = sentinel) :
    if foo is sentinel :
       foo = {}
    # other stuff



More information about the Python-list mailing list