list of class instances within a list of a class instances

Discussion in 'Python' started by John Wohlbier, Feb 22, 2004.

  1. Hi,

    I have a basic programming question regarding classes
    in python. I want to have a list of "primaryClass"
    instances, and in each instance of primaryClass I would
    like a list of "subClass" instances. When each primaryClass
    instance is created I want to put one instance of subClass
    into the "sClasses" list (see code). The attached
    code is what I came up with, but it doesn't do what I
    want. For some reason the "sClasses" list in each primaryClass
    instance is the same! That is, when a new primaryClass is instantiated,
    and the .append(subClass()) is called in the constructor, the
    subClass is appended to ALL instances of primaryClass, instead
    of just the new instance of primaryClass. The
    print statements in the code confirm this.

    I think I must be missing something fundamental. Thanks
    in advance.

    jgw

    ======================================================================


    ###############################################################################
    class primaryClass:
    name=""
    sClasses = []

    def __init__(self,name):
    self.name = name
    self.sClasses.append(subClass("default"))
    ###############################################################################
    class subClass:
    name=""

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

    ###############################################################################


    port = [] # make a list
    port.append(primaryClass("firstclass"))

    print 'port contents'
    for i in range(len(port)):
    print i, port.name
    for j in range(len(port.sClasses)):
    print i, j, port.sClasses[j].name

    port.append(primaryClass("secondclass"))
    print 'port contents'
    for i in range(len(port)):
    print i, port.name
    for j in range(len(port.sClasses)):
    print i, j, port.sClasses[j].name

    port.append(primaryClass("thirdclass"))
    print 'port contents'
    for i in range(len(port)):
    print i, port.name
    for j in range(len(port.sClasses)):
    print i, j, port.sClasses[j].name
     
    John Wohlbier, Feb 22, 2004
    #1
    1. Advertising

  2. John Wohlbier

    Peter Otten Guest

    John Wohlbier wrote:

    > class primaryClass:


    Remove the following two lines. Variables you put here are shared between
    all instances of the class.

    > name=""
    > sClasses = []
    >
    > def __init__(self,name):

    self.sClasses = [] # now you'll get a new list for each instance
    > self.name = name
    > self.sClasses.append(subClass("default"))
    >

    ###############################################################################
    > class subClass:


    The following line is superfluous.

    > name=""
    >
    > def __init__(self,name):
    > self.name = name
    >
    >

    ###############################################################################

    >
    >
    > port = [] # make a list
    > port.append(primaryClass("firstclass"))
    >
    > print 'port contents'


    More idiomatic is:
    for p in port:
    print p.name
    for s in s.sClasses:
    #...
    Or, if you really need the indices:

    for i, p in enumerate(port):
    print i, p.name
    #...

    > for i in range(len(port)):
    > print i, port.name
    > for j in range(len(port.sClasses)):
    > print i, j, port.sClasses[j].name
    >
    > port.append(primaryClass("secondclass"))


    Hey, I've seen the following section before. Never duplicate code - that's
    what functions are for.

    > print 'port contents'
    > for i in range(len(port)):
    > print i, port.name
    > for j in range(len(port.sClasses)):
    > print i, j, port.sClasses[j].name
    >
    > port.append(primaryClass("thirdclass"))
    > print 'port contents'
    > for i in range(len(port)):
    > print i, port.name
    > for j in range(len(port.sClasses)):
    > print i, j, port.sClasses[j].name



    Peter
     
    Peter Otten, Feb 22, 2004
    #2
    1. Advertising

  3. > class primaryClass:
    > name=""
    > sClasses = []
    >
    > def __init__(self,name):
    > self.name = name
    > self.sClasses.append(subClass("default"))


    Try the below instead.

    class primaryClass:
    def __init__(self,name):
    self.name = name
    self.sClasses = [subClass("default")]

    In general, everything defined in the class-level scope is shared among
    all instances of that class, even before creation. When you re-assign
    'name' in __init__ in your original version, or really anywhere else,
    'name' is no longer referring to the shared 'primaryClass.name' object,
    it is referring to the object assigned. When you used
    self.sClasses.append(), you were modifying the shared list in-place,
    which is why all instances of primaryClass shared the list.

    Also, you don't need to define all class variables (or really any)
    outside in the class-level scope. It is convenient for some shared
    immutables (strings, integers, tuples, floats, functions) on occasion,
    but unless you know what you are doing with the mutables (lists,
    dictionaries, arrays (from the array module), etc.), you should be careful.

    - Josiah
     
    Josiah Carlson, Feb 22, 2004
    #3
    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. KatB
    Replies:
    0
    Views:
    449
  2. Riccardo Murri
    Replies:
    3
    Views:
    487
    Gabriel Genellina
    Dec 30, 2007
  3. Replies:
    8
    Views:
    469
    James Stroud
    Jan 29, 2009
  4. Robert Somerville
    Replies:
    0
    Views:
    250
    Robert Somerville
    Apr 19, 2010
  5. Gnarlodious
    Replies:
    5
    Views:
    202
    Gnarlodious
    Nov 2, 2011
Loading...

Share This Page