initialising a list of lists

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Peter Kleiweg

    #1

    initialising a list of lists


    This does not what I want it to do:
    [color=blue][color=green][color=darkred]
    >>> a = [[]] * 6
    >>> a[3].append('X')
    >>> a[/color][/color][/color]
    [['X'], ['X'], ['X'], ['X'], ['X'], ['X']]

    This does what I want:
    [color=blue][color=green][color=darkred]
    >>> b = [[] for _ in range(6)]
    >>> b[3].append('X')
    >>> b[/color][/color][/color]
    [[], [], [], ['X'], [], []]

    The first is clear and wrong. The second is hairy and right.
    Is there a way to do it clear and right?

    --
    Peter Kleiweg L:NL,af,da,de,e n,ia,nds,no,sv, (fr,it) S:NL,de,en,(da, ia)
    info: http://www.let.rug.nl/~kleiweg/ls.html
  • Fredrik Lundh

    #2
    Re: initialising a list of lists

    Peter Kleiweg wrote:
    [color=blue]
    > This does not what I want it to do:
    >[color=green][color=darkred]
    > >>> a = [[]] * 6
    > >>> a[3].append('X')
    > >>> a[/color][/color]
    > [['X'], ['X'], ['X'], ['X'], ['X'], ['X']]
    >
    > This does what I want:
    >[color=green][color=darkred]
    > >>> b = [[] for _ in range(6)]
    > >>> b[3].append('X')
    > >>> b[/color][/color]
    > [[], [], [], ['X'], [], []]
    >
    > The first is clear and wrong. The second is hairy and right.
    > Is there a way to do it clear and right?[/color]



    </F>



    Comment

    • Fredrik Lundh

      #3
      Re: initialising a list of lists

      Peter Kleiweg wrote:
      [color=blue]
      > This does not what I want it to do:
      >[color=green][color=darkred]
      > >>> a = [[]] * 6
      > >>> a[3].append('X')
      > >>> a[/color][/color]
      > [['X'], ['X'], ['X'], ['X'], ['X'], ['X']]
      >
      > This does what I want:
      >[color=green][color=darkred]
      > >>> b = [[] for _ in range(6)]
      > >>> b[3].append('X')
      > >>> b[/color][/color]
      > [[], [], [], ['X'], [], []]
      >
      > The first is clear and wrong. The second is hairy and right.
      > Is there a way to do it clear and right?[/color]



      </F>



      Comment

      • Peter Kleiweg

        #4
        Re: initialising a list of lists

        Fredrik Lundh schreef op de 16e dag van de slachtmaand van het jaar 2005:
        [color=blue]
        > Peter Kleiweg wrote:
        >[color=green]
        > > This does not what I want it to do:
        > >[color=darkred]
        > > >>> a = [[]] * 6
        > > >>> a[3].append('X')
        > > >>> a[/color]
        > > [['X'], ['X'], ['X'], ['X'], ['X'], ['X']]
        > >
        > > This does what I want:
        > >[color=darkred]
        > > >>> b = [[] for _ in range(6)]
        > > >>> b[3].append('X')
        > > >>> b[/color]
        > > [[], [], [], ['X'], [], []]
        > >
        > > The first is clear and wrong. The second is hairy and right.
        > > Is there a way to do it clear and right?[/color]
        >
        > http://www.python.org/doc/faq/progra...mensional-list[/color]

        In other words: no there isn't.

        --
        Peter Kleiweg L:NL,af,da,de,e n,ia,nds,no,sv, (fr,it) S:NL,de,en,(da, ia)
        info: http://www.let.rug.nl/~kleiweg/ls.html

        Comment

        • Peter Kleiweg

          #5
          Re: initialising a list of lists

          Fredrik Lundh schreef op de 16e dag van de slachtmaand van het jaar 2005:
          [color=blue]
          > Peter Kleiweg wrote:
          >[color=green]
          > > This does not what I want it to do:
          > >[color=darkred]
          > > >>> a = [[]] * 6
          > > >>> a[3].append('X')
          > > >>> a[/color]
          > > [['X'], ['X'], ['X'], ['X'], ['X'], ['X']]
          > >
          > > This does what I want:
          > >[color=darkred]
          > > >>> b = [[] for _ in range(6)]
          > > >>> b[3].append('X')
          > > >>> b[/color]
          > > [[], [], [], ['X'], [], []]
          > >
          > > The first is clear and wrong. The second is hairy and right.
          > > Is there a way to do it clear and right?[/color]
          >
          > http://www.python.org/doc/faq/progra...mensional-list[/color]

          In other words: no there isn't.

          --
          Peter Kleiweg L:NL,af,da,de,e n,ia,nds,no,sv, (fr,it) S:NL,de,en,(da, ia)
          info: http://www.let.rug.nl/~kleiweg/ls.html

          Comment

          • Daniel Dittmar

            #6
            Re: initialising a list of lists

            Peter Kleiweg wrote:[color=blue]
            > This does not what I want it to do:
            >[color=green][color=darkred]
            > >>> a = [[]] * 6
            > >>> a[3].append('X')
            > >>> a[/color][/color]
            > [['X'], ['X'], ['X'], ['X'], ['X'], ['X']]
            >
            > This does what I want:
            >[color=green][color=darkred]
            > >>> b = [[] for _ in range(6)]
            > >>> b[3].append('X')
            > >>> b[/color][/color]
            > [[], [], [], ['X'], [], []]
            >
            > The first is clear and wrong. The second is hairy and right.[/color]
            [color=blue]
            > Is there a way to do it clear[/color]

            Define a function:

            import copy

            def init_list (count, element):
            return [copy.copy (element) for i in xrange (count)]
            [color=blue]
            > and right?[/color]

            Test it.

            Daniel

            Comment

            • Daniel Dittmar

              #7
              Re: initialising a list of lists

              Peter Kleiweg wrote:[color=blue]
              > This does not what I want it to do:
              >[color=green][color=darkred]
              > >>> a = [[]] * 6
              > >>> a[3].append('X')
              > >>> a[/color][/color]
              > [['X'], ['X'], ['X'], ['X'], ['X'], ['X']]
              >
              > This does what I want:
              >[color=green][color=darkred]
              > >>> b = [[] for _ in range(6)]
              > >>> b[3].append('X')
              > >>> b[/color][/color]
              > [[], [], [], ['X'], [], []]
              >
              > The first is clear and wrong. The second is hairy and right.[/color]
              [color=blue]
              > Is there a way to do it clear[/color]

              Define a function:

              import copy

              def init_list (count, element):
              return [copy.copy (element) for i in xrange (count)]
              [color=blue]
              > and right?[/color]

              Test it.

              Daniel

              Comment

              • Fredrik Lundh

                #8
                Re: initialising a list of lists

                Peter Kleiweg wrote:
                [color=blue][color=green]
                >> http://www.python.org/doc/faq/progra...mensional-list[/color]
                >
                > In other words: no there isn't.[/color]

                For people who actually knows Python, a list comprehension is clear and
                obviously correct.

                For people who actually knows Python, your first solution is also obviously
                wrong. To create a new list objects, you have to execute the list display.
                New objects never appear out of the blue, and Python hardly ever copies
                objects unless you tell it to do so.

                </F>



                Comment

                • Fredrik Lundh

                  #9
                  Re: initialising a list of lists

                  Peter Kleiweg wrote:
                  [color=blue][color=green]
                  >> http://www.python.org/doc/faq/progra...mensional-list[/color]
                  >
                  > In other words: no there isn't.[/color]

                  For people who actually knows Python, a list comprehension is clear and
                  obviously correct.

                  For people who actually knows Python, your first solution is also obviously
                  wrong. To create a new list objects, you have to execute the list display.
                  New objects never appear out of the blue, and Python hardly ever copies
                  objects unless you tell it to do so.

                  </F>



                  Comment

                  • Steven D'Aprano

                    #10
                    Re: initialising a list of lists

                    On Wed, 16 Nov 2005 13:58:45 +0100, Peter Kleiweg wrote:
                    [color=blue]
                    >
                    > This does not what I want it to do:
                    >[color=green][color=darkred]
                    > >>> a = [[]] * 6
                    > >>> a[3].append('X')
                    > >>> a[/color][/color]
                    > [['X'], ['X'], ['X'], ['X'], ['X'], ['X']]
                    >
                    > This does what I want:
                    >[color=green][color=darkred]
                    > >>> b = [[] for _ in range(6)]
                    > >>> b[3].append('X')
                    > >>> b[/color][/color]
                    > [[], [], [], ['X'], [], []]
                    >
                    > The first is clear and wrong.[/color]

                    That is correct. It is wrong because you make six references to the same
                    empty list instead of six different empty lists.
                    [color=blue]
                    > The second is hairy and right.[/color]

                    I disagree. I think the second method is just as clear as the first.
                    [color=blue]
                    > Is there a way to do it clear and right?[/color]

                    There are lots of ways to do it right. Clarity is in the eye of the
                    beholder. But perhaps the clearest way is the most explicit:
                    [color=blue][color=green][color=darkred]
                    >>> c = []
                    >>> for i in range(6):[/color][/color][/color]
                    .... c.append([])[color=blue][color=green][color=darkred]
                    >>> c[3].append('X')
                    >>> c[/color][/color][/color]
                    [[], [], [], ['X'], [], []]


                    I can't help feeling though that this is such a common task, and so often
                    trips up newbies, that it deserves a built in list method. I base my
                    reasoning on the existence of methods like extend:

                    Instead of writing:

                    for item in seq:
                    L.append(item)

                    the Powers That Be created L.extend(seq). This isn't the only case of very
                    simple idioms being made even shorter in Python.

                    So perhaps there should be a list method that takes an integer argument
                    and appends that many empty lists:

                    d = []
                    d.append_emptie s(5)

                    Or even a function that does this:

                    def nested(numcopie s, base=None, *args):
                    if base is None:
                    base = []
                    for i in range(numcopies ):
                    base.append(arg s[:])
                    return base





                    --
                    Steven.

                    Comment

                    • Steven D'Aprano

                      #11
                      Re: initialising a list of lists

                      On Wed, 16 Nov 2005 13:58:45 +0100, Peter Kleiweg wrote:
                      [color=blue]
                      >
                      > This does not what I want it to do:
                      >[color=green][color=darkred]
                      > >>> a = [[]] * 6
                      > >>> a[3].append('X')
                      > >>> a[/color][/color]
                      > [['X'], ['X'], ['X'], ['X'], ['X'], ['X']]
                      >
                      > This does what I want:
                      >[color=green][color=darkred]
                      > >>> b = [[] for _ in range(6)]
                      > >>> b[3].append('X')
                      > >>> b[/color][/color]
                      > [[], [], [], ['X'], [], []]
                      >
                      > The first is clear and wrong.[/color]

                      That is correct. It is wrong because you make six references to the same
                      empty list instead of six different empty lists.
                      [color=blue]
                      > The second is hairy and right.[/color]

                      I disagree. I think the second method is just as clear as the first.
                      [color=blue]
                      > Is there a way to do it clear and right?[/color]

                      There are lots of ways to do it right. Clarity is in the eye of the
                      beholder. But perhaps the clearest way is the most explicit:
                      [color=blue][color=green][color=darkred]
                      >>> c = []
                      >>> for i in range(6):[/color][/color][/color]
                      .... c.append([])[color=blue][color=green][color=darkred]
                      >>> c[3].append('X')
                      >>> c[/color][/color][/color]
                      [[], [], [], ['X'], [], []]


                      I can't help feeling though that this is such a common task, and so often
                      trips up newbies, that it deserves a built in list method. I base my
                      reasoning on the existence of methods like extend:

                      Instead of writing:

                      for item in seq:
                      L.append(item)

                      the Powers That Be created L.extend(seq). This isn't the only case of very
                      simple idioms being made even shorter in Python.

                      So perhaps there should be a list method that takes an integer argument
                      and appends that many empty lists:

                      d = []
                      d.append_emptie s(5)

                      Or even a function that does this:

                      def nested(numcopie s, base=None, *args):
                      if base is None:
                      base = []
                      for i in range(numcopies ):
                      base.append(arg s[:])
                      return base





                      --
                      Steven.

                      Comment

                      Working...