Unexpected behavior when initializing class

Discussion in 'Python' started by alfred.fazio@gmail.com, Nov 28, 2007.

  1. Guest

    Hello everybody,

    I've banged my ahead around for a while trying to figure out why
    multiple instances of a class share the same instance variable. I've
    stripped down my code to the following, which reproduces my problem.

    class Test(object):
    def __init__(self, v=[]):
    self.values = v

    def addValue(self, v):
    self.values += [v]
    return

    a = Test()
    a.addValue(1)
    print a.values # Should print [1]
    b = Test()
    print b.values # Should print empty list
    b.addValue(2)
    print a.values # Should print [1]

    The output I get is:

    [1]
    [1]
    [1, 2]

    The output I am expecting is:

    [1]
    []
    [1]

    Another strange thing is that if I initialize with a different value,
    the new instance will not share the 'values' attribute with the other
    two:

    c = Test([9])
    print c.values # Prints [9] as it should
    print a.values # Still prints [1, 2]

    There is something I clearly don't understand here. Can anybody
    explain? Thanks!

    Python 2.4.4 (#1, Oct 23 2006, 13:58:18)
    [GCC 4.1.1 20061011 (Red Hat 4.1.1-30)] on linux2

    Alfred J. Fazio,
    , Nov 28, 2007
    #1
    1. Advertising

  2. Paul Rudin Guest

    "" <> writes:

    > Hello everybody,
    >
    > I've banged my ahead around for a while trying to figure out why
    > multiple instances of a class share the same instance variable. I've
    > stripped down my code to the following, which reproduces my problem.
    >
    > class Test(object):
    > def __init__(self, v=[]):
    > self.values = v


    You have to understand that the default value for v - an empty list -
    is made at compile time - and it's the *same* list every time it's
    used i.e. if you don't pass in a value for v when you make new
    instances of your class.

    A common paradigm to get round this - assuming you want a different
    empty list each time - is something like:

    def __init__(self, v = None):
    self.values = v if v else []

    (or maybe test explicitly for None, but you get the idea.)
    Paul Rudin, Nov 28, 2007
    #2
    1. Advertising

  3. Guest

    On Nov 28, 3:31 am, Paul Rudin <> wrote:
    > You have to understand that the default value for v - an empty list -
    > is made at compile time - and it's the *same* list every time it's
    > used i.e. if you don't pass in a value for v when you make new
    > instances of your class.


    *smack*!! That's me smacking myself on the forehead. I now remember
    reading a long time ago that this was an FAQ! Thanks for the reply,
    Paul. :)

    Alfred J. Fazio,
    , Nov 28, 2007
    #3
  4. Gary Herron Guest

    wrote:
    > Hello everybody,
    >
    > I've banged my ahead around for a while trying to figure out why
    > multiple instances of a class share the same instance variable. I've
    > stripped down my code to the following, which reproduces my problem.
    >


    This is a *feature* of Python that bytes *ever* newbie at least once. ;-)

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

    > class Test(object):
    > def __init__(self, v=[]):
    > self.values = v
    >
    > def addValue(self, v):
    > self.values += [v]
    > return
    >
    > a = Test()
    > a.addValue(1)
    > print a.values # Should print [1]
    > b = Test()
    > print b.values # Should print empty list
    > b.addValue(2)
    > print a.values # Should print [1]
    >
    > The output I get is:
    >
    > [1]
    > [1]
    > [1, 2]
    >
    > The output I am expecting is:
    >
    > [1]
    > []
    > [1]
    >
    > Another strange thing is that if I initialize with a different value,
    > the new instance will not share the 'values' attribute with the other
    > two:
    >
    > c = Test([9])
    > print c.values # Prints [9] as it should
    > print a.values # Still prints [1, 2]
    >
    > There is something I clearly don't understand here. Can anybody
    > explain? Thanks!
    >
    > Python 2.4.4 (#1, Oct 23 2006, 13:58:18)
    > [GCC 4.1.1 20061011 (Red Hat 4.1.1-30)] on linux2
    >
    > Alfred J. Fazio,
    >
    >
    Gary Herron, Nov 28, 2007
    #4
  5. John Machin Guest

    On Nov 28, 7:19 pm, "" <>
    wrote:
    > Hello everybody,
    >
    > I've banged my ahead around for a while trying to figure out why
    > multiple instances of a class share the same instance variable. I've
    > stripped down my code to the following, which reproduces my problem.
    >
    > class Test(object):
    > def __init__(self, v=[]):
    > self.values = v
    >
    > def addValue(self, v):
    > self.values += [v]
    > return
    >
    > a = Test()
    > a.addValue(1)
    > print a.values # Should print [1]
    > b = Test()
    > print b.values # Should print empty list
    > b.addValue(2)
    > print a.values # Should print [1]
    >
    > The output I get is:
    >
    > [1]
    > [1]
    > [1, 2]
    >
    > The output I am expecting is:
    >
    > [1]
    > []
    > [1]
    >
    > Another strange thing is that if I initialize with a different value,
    > the new instance will not share the 'values' attribute with the other
    > two:
    >
    > c = Test([9])
    > print c.values # Prints [9] as it should
    > print a.values # Still prints [1, 2]
    >
    > There is something I clearly don't understand here. Can anybody
    > explain? Thanks!


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

    http://docs.python.org/tut/node6.html#SECTION006710000000000000000
    John Machin, Nov 28, 2007
    #5
  6. Duncan Booth Guest

    Paul Rudin <> wrote:

    > You have to understand that the default value for v - an empty list -
    > is made at compile time


    Not at compile time: the default value is created at runtime when the def
    statement is executed.
    Duncan Booth, Nov 28, 2007
    #6
  7. Mel Guest

    Paul Rudin wrote:
    > "" <> writes:


    > A common paradigm to get round this - assuming you want a different
    > empty list each time - is something like:
    >
    > def __init__(self, v = None):
    > self.values = v if v else []
    >
    > (or maybe test explicitly for None, but you get the idea.)


    Do test explicitly for None. Otherwise, if you do

    a = []
    x = ThatClass (a)


    it will so happen that x.values will be an empty list, but it won't be
    the same list as a.

    Mel.
    Mel, Nov 28, 2007
    #7
  8. On Nov 28, 3:04 pm, Mel <> wrote:
    > Paul Rudin wrote:
    > > "" <> writes:
    > > A common paradigm to get round this - assuming you want a different
    > > empty list each time - is something like:

    >
    > > def __init__(self, v = None):
    > > self.values = v if v else []

    >
    > > (or maybe test explicitly for None, but you get the idea.)

    >
    > Do test explicitly for None. Otherwise, if you do
    >
    > a = []
    > x = ThatClass (a)
    >
    > it will so happen that x.values will be an empty list, but it won't be
    > the same list as a.
    >
    > Mel.


    Yes. Another much safer possibility is to make a copy of the initial
    v:

    def __init__(self, values=[]):
    self.values = list(values)

    As a nice side effect, the object can be initialised with any
    iterable.

    --
    Arnaud
    Arnaud Delobelle, Nov 28, 2007
    #8
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. G Dean Blake

    Unexpected datagrid behavior

    G Dean Blake, Jan 13, 2005, in forum: ASP .Net
    Replies:
    0
    Views:
    313
    G Dean Blake
    Jan 13, 2005
  2. Chuck Bowling

    Unexpected page designer behavior

    Chuck Bowling, Jul 4, 2005, in forum: ASP .Net
    Replies:
    1
    Views:
    439
    Chuck Bowling
    Jul 4, 2005
  3. Victor Bazarov
    Replies:
    0
    Views:
    846
    Victor Bazarov
    Jun 25, 2003
  4. Rob Clewley
    Replies:
    3
    Views:
    229
    Rob Clewley
    Jan 13, 2009
  5. Thomas Draper
    Replies:
    2
    Views:
    176
    Steven D'Aprano
    Aug 7, 2012
Loading...

Share This Page