Jumping around when assigning elements

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Matthew Sims

    Jumping around when assigning elements

    Python Newbie here. This is my first time learning object-oriented
    programming and trying to break out of the usual Korn/Perl/PHP style
    of programming. Having some difficulty understand some items.

    For lists, I understand this:
    C=["need","some"," help"]
    print C[1]
    some

    But I can't seem to do this:
    C[3]="here"

    I know about C.append("here" ) but this brings me to my question...

    Is there anyway to assign to an element that wasn't defined in the
    beginning? Like if I wanted element 5 assigned but not element 4
    without using "" or None?

    I'm currently re-writing a Perl script into Python and with Perl I was
    free to assign any element in the array without having to fill in the
    previous elements. I can't seem to do that in Python...unless I'm
    doing it wrong.

    Thanks
    --Matt
  • Francis Avila

    #2
    Re: Jumping around when assigning elements

    Matthew Sims wrote in message
    <1e963607.03121 51408.583221e6@ posting.google. com>...[color=blue]
    >Python Newbie here. This is my first time learning object-oriented
    >programming and trying to break out of the usual Korn/Perl/PHP style
    >of programming. Having some difficulty understand some items.
    >
    >For lists, I understand this:
    >C=["need","some"," help"]
    >print C[1]
    >some
    >
    >But I can't seem to do this:
    >C[3]="here"
    >
    >I know about C.append("here" ) but this brings me to my question...
    >
    >Is there anyway to assign to an element that wasn't defined in the
    >beginning? Like if I wanted element 5 assigned but not element 4
    >without using "" or None?[/color]

    I assume you tried 'insert'?[color=blue][color=green][color=darkred]
    >>> C=["need","some"," help"]
    >>> C.insert(10, 'here')
    >>> C[/color][/color][/color]
    ['need', 'some', 'help', 'here']

    Ah, well that didn't work. Python has no (builtin) way to do what you want.
    The reason isn't technical, but that the list needs *something* in that
    intervening space, and Python isn't about to make rash presumptions about
    what you want there ("explicit is better than implicit"). In choosing
    between two behaviors for inserting to an index beyond the end of a list,
    appending was deemed less surprising, less violent, and less likely to
    introduce mysterious bugs than filling in the intermediate elements with
    who-knows-what.

    I can't even think of why one would want lists to have that sort of
    behavior. It seems to me that if we're assigning to arbitrary elements and
    we want the list to grow with it, that we should be using a different data
    structure, like a dictionary with integer keys. The index of a list
    generally has no semantic correlation to the data contained therein--it just
    specifies order, and the data doesn't care about its own index. If we want
    a semantic correlation, we make that correlation explicit by a dictionary's
    key-value pair.

    If you want to do this sort of thing (implicit assignment to intermediate
    elements in list insertions), write a function to do it, or subclass list.
    You can even modify the slice behavior itself (if you go the subclass
    route), so that C[3] will silently act like perl instead of Python, but this
    is *quite* unPythonic. (Other Python people reading your code will be
    confused.)

    If this sort of answer surprises you (coming from perl, it might...), do an
    "import this" at an interactive prompt and read. :)
    [color=blue]
    >I'm currently re-writing a Perl script into Python and with Perl I was
    >free to assign any element in the array without having to fill in the
    >previous elements. I can't seem to do that in Python...unless I'm
    >doing it wrong.[/color]

    Again, in general, Python has *no* implicit
    assignments/declarations/modifications/etc. If you don't *explicitly* ask a
    list to fill in its intermediate elements, Python won't do it. This is a
    conscious design decision, and a great part of what makes Python Python.
    For at least two senses of "great", IMO.

    I could never learn perl (despite many attempts), so I ask, what does perl
    do to the intermediate elements? Is a perl array more like a dictionary
    with implicit integer keys (so intermediate keys simply don't exist), or
    does it fill in the intermediate elements with 0 or something like that? In
    what perl idioms is this behavior useful? (I still mean to learn perl one
    of these days, for shell scripting.)
    --
    Francis Avila

    Comment

    • Mike Rovner

      #3
      Re: Jumping around when assigning elements

      Francis Avila wrote:[color=blue]
      > Matthew Sims wrote in message[color=green]
      >> of programming. Having some difficulty understand some items.
      >>
      >> I'm currently re-writing a Perl script into Python and with Perl I
      >> was free to assign any element in the array without having to fill
      >> in the previous elements. I can't seem to do that in Python...unless
      >> I'm doing it wrong.[/color]
      >
      > Again, in general, Python has *no* implicit
      > assignments/declarations/modifications/etc. If you don't
      > *explicitly* ask a list to fill in its intermediate elements, Python
      > won't do it. This is a conscious design decision, and a great part
      > of what makes Python Python. For at least two senses of "great", IMO.[/color]

      As were stated here many times it's not a good idea to mechanicaly
      translate perl to python, they are quite different in approaches
      despite similar syntax and capabilities.
      Better understand initial script logic and write python from scratch.
      In your case it might be list, dictionary or even none of them, so
      it's highly dependent on the task at hand.
      [color=blue]
      > I could never learn perl (despite many attempts), so I ask, what does
      > perl do to the intermediate elements? Is a perl array more like a
      > dictionary with implicit integer keys (so intermediate keys simply
      > don't exist), or does it fill in the intermediate elements with 0 or
      > something like that? In what perl idioms is this behavior useful?
      > (I still mean to learn perl one of these days, for shell scripting.)[/color]

      perl doesn't assigns them, they are 'undef', so it's more like python's dict

      Mike




      Comment

      • Peter Otten

        #4
        Re: Jumping around when assigning elements

        Matthew Sims wrote:
        [color=blue]
        > Is there anyway to assign to an element that wasn't defined in the
        > beginning? Like if I wanted element 5 assigned but not element 4
        > without using "" or None?[/color]

        You can write your own class:

        class GrowingList(lis t):
        def __init__(self, seq, default=None):
        list.__init__(s elf, seq)
        self.default = default
        def __setitem__(sel f, index, value):
        if index >= len(self):
        self.extend([self.default]*(index - len(self)))
        self.append(val ue)
        else:
        list.__setitem_ _(self, index, value)


        g = GrowingList(["alpha", "beta", "gamma"])
        g[7] = "omega"
        print g

        This is a partial implementation, only g[index] = value will work.
        [color=blue]
        > I'm currently re-writing a Perl script into Python and with Perl I was
        > free to assign any element in the array without having to fill in the
        > previous elements. I can't seem to do that in Python...unless I'm
        > doing it wrong.[/color]

        As already pointed out, a mechanical translation will yield substandard
        results. As you did not describe the problem you are solving with the
        "autogrowin g" list, there is little chance for us to come up with a better
        or at least more idiomatic approach.

        Peter

        PS: Welcome to the worst programming language - except all others :-)






        Comment

        • Cameron Laird

          #5
          Re: Jumping around when assigning elements

          In article <brljag$ihk$01$ 1@news.t-online.com>,
          Peter Otten <__peter__@web. de> wrote:[color=blue]
          >Matthew Sims wrote:
          >[color=green]
          >> Is there anyway to assign to an element that wasn't defined in the
          >> beginning? Like if I wanted element 5 assigned but not element 4
          >> without using "" or None?[/color]
          >
          >You can write your own class:
          >
          >class GrowingList(lis t):
          > def __init__(self, seq, default=None):
          > list.__init__(s elf, seq)
          > self.default = default
          > def __setitem__(sel f, index, value):
          > if index >= len(self):
          > self.extend([self.default]*(index - len(self)))
          > self.append(val ue)
          > else:
          > list.__setitem_ _(self, index, value)
          >
          >
          >g = GrowingList(["alpha", "beta", "gamma"])
          >g[7] = "omega"
          >print g
          >
          >This is a partial implementation, only g[index] = value will work.
          >[color=green]
          >> I'm currently re-writing a Perl script into Python and with Perl I was
          >> free to assign any element in the array without having to fill in the
          >> previous elements. I can't seem to do that in Python...unless I'm
          >> doing it wrong.[/color]
          >
          >As already pointed out, a mechanical translation will yield substandard
          >results. As you did not describe the problem you are solving with the
          >"autogrowing " list, there is little chance for us to come up with a better
          >or at least more idiomatic approach.[/color]

          Comment

          • Matthew Sims

            #6
            Re: Jumping around when assigning elements

            "Francis Avila" <francisgavila@ yahoo.com> wrote in message news:<vtsgvm4d0 dk157@corp.supe rnews.com>...[color=blue]
            > Matthew Sims wrote in message
            > <1e963607.03121 51408.583221e6@ posting.google. com>...[color=green]
            > >Python Newbie here. This is my first time learning object-oriented
            > >programming and trying to break out of the usual Korn/Perl/PHP style
            > >of programming. Having some difficulty understand some items.
            > >
            > >For lists, I understand this:
            > >C=["need","some"," help"]
            > >print C[1]
            > >some
            > >
            > >But I can't seem to do this:
            > >C[3]="here"
            > >
            > >I know about C.append("here" ) but this brings me to my question...
            > >
            > >Is there anyway to assign to an element that wasn't defined in the
            > >beginning? Like if I wanted element 5 assigned but not element 4
            > >without using "" or None?[/color]
            >
            > I assume you tried 'insert'?[color=green][color=darkred]
            > >>> C=["need","some"," help"]
            > >>> C.insert(10, 'here')
            > >>> C[/color][/color]
            > ['need', 'some', 'help', 'here']
            >
            > Ah, well that didn't work. Python has no (builtin) way to do what you want.
            > The reason isn't technical, but that the list needs *something* in that
            > intervening space, and Python isn't about to make rash presumptions about
            > what you want there ("explicit is better than implicit"). In choosing
            > between two behaviors for inserting to an index beyond the end of a list,
            > appending was deemed less surprising, less violent, and less likely to
            > introduce mysterious bugs than filling in the intermediate elements with
            > who-knows-what.[/color]

            First off...I still have a lot to learn. :)
            [color=blue]
            >
            > I can't even think of why one would want lists to have that sort of
            > behavior. It seems to me that if we're assigning to arbitrary elements and
            > we want the list to grow with it, that we should be using a different data
            > structure, like a dictionary with integer keys. The index of a list
            > generally has no semantic correlation to the data contained therein--it just
            > specifies order, and the data doesn't care about its own index. If we want
            > a semantic correlation, we make that correlation explicit by a dictionary's
            > key-value pair.
            >
            > If you want to do this sort of thing (implicit assignment to intermediate
            > elements in list insertions), write a function to do it, or subclass list.
            > You can even modify the slice behavior itself (if you go the subclass
            > route), so that C[3] will silently act like perl instead of Python, but this
            > is *quite* unPythonic. (Other Python people reading your code will be
            > confused.)[/color]

            My guess is that this is what makes OO programming different than
            modular.
            [color=blue]
            >
            > If this sort of answer surprises you (coming from perl, it might...), do an
            > "import this" at an interactive prompt and read. :)
            >[/color]

            The Zen of Python, by Tim Peters...heh
            [color=blue][color=green]
            > >I'm currently re-writing a Perl script into Python and with Perl I was
            > >free to assign any element in the array without having to fill in the
            > >previous elements. I can't seem to do that in Python...unless I'm
            > >doing it wrong.[/color]
            >
            > Again, in general, Python has *no* implicit
            > assignments/declarations/modifications/etc. If you don't *explicitly* ask a
            > list to fill in its intermediate elements, Python won't do it. This is a
            > conscious design decision, and a great part of what makes Python Python.
            > For at least two senses of "great", IMO.
            >
            > I could never learn perl (despite many attempts), so I ask, what does perl
            > do to the intermediate elements? Is a perl array more like a dictionary
            > with implicit integer keys (so intermediate keys simply don't exist), or
            > does it fill in the intermediate elements with 0 or something like that? In
            > what perl idioms is this behavior useful? (I still mean to learn perl one
            > of these days, for shell scripting.)[/color]

            Here's how the program basically worked. It's for a Tape Library with
            a robot arm in the middle. There are 40 slots and each is represented
            as an element in the array. If a tape was in one of the slots, that
            element # corresponds to the slot # and the tape ID would show in that
            element. All other elements represented blank slots. This allowed me
            to control the robot arm to the exact slot a tape resides since all I
            had to do was look at any elements that had tape IDs assigned.

            So far the only way I could get this to work in Python was to insert
            "" to represent an empty slot. But Python counts "" when I want to see
            how many tapes are currently taking up slots "len(SLOTS) ". It would
            always show 40. So I now know that I need to write code to tell Python
            not to count "". Not too difficult.

            I guess I'm realizing how I need to approach Python as my first OO.
            I'm re-writing the script as sort of a training. The program works
            flawlessly in Perl, I'm just doing it to learn. So far it has taken
            less lines of code in Python to perform the same tasks in Perl...up
            til this point. ;)

            Anyways, I appreciate the responses. I have a better understand of
            Python.

            --Matt

            Comment

            • Andrew Bennetts

              #7
              Re: Jumping around when assigning elements

              On Mon, Dec 15, 2003 at 06:57:19PM -0800, Matthew Sims wrote:
              [...][color=blue]
              >
              > So far the only way I could get this to work in Python was to insert
              > "" to represent an empty slot. But Python counts "" when I want to see
              > how many tapes are currently taking up slots "len(SLOTS) ". It would
              > always show 40. So I now know that I need to write code to tell Python
              > not to count "". Not too difficult.
              >
              > I guess I'm realizing how I need to approach Python as my first OO.
              > I'm re-writing the script as sort of a training. The program works
              > flawlessly in Perl, I'm just doing it to learn. So far it has taken
              > less lines of code in Python to perform the same tasks in Perl...up
              > til this point. ;)[/color]

              It sounds like your problem isn't OO, but the wrong choice of datastructure.
              As someone else in this thread has already said, you want a dictionary
              (known as a 'hash' in perl), not a list. Among other things, len(some_dict)
              will give you the result you expect.

              -Andrew.


              Comment

              • Shalabh Chaturvedi

                #8
                Re: Jumping around when assigning elements

                matt@killermook ie.org (Matthew Sims) wrote in message news:<1e963607. 0312151408.5832 21e6@posting.go ogle.com>...
                [color=blue]
                > For lists, I understand this:
                > C=["need","some"," help"]
                > print C[1]
                > some
                >
                > But I can't seem to do this:
                > C[3]="here"
                >
                > I know about C.append("here" ) but this brings me to my question...
                >
                > Is there anyway to assign to an element that wasn't defined in the
                > beginning? Like if I wanted element 5 assigned but not element 4
                > without using "" or None?[/color]

                You could try using a dictionary instead of a list. You could even
                initialize the dict from the list:

                l = ["just", "a", "suggestion "]
                d = {}
                for k,v in enumerate(l):
                d[k] = v

                d[10] = "here"

                Of course, to get at the values now, you would need to iterate over
                d.values(). Note that you won't necessarily get the values in sorted
                order of keys. You would have to do that explicitly if you want.

                --
                Shalabh

                Comment

                • Francis Avila

                  #9
                  Re: Jumping around when assigning elements

                  Matthew Sims wrote in message
                  <1e963607.03121 51857.186adaa8@ posting.google. com>...[color=blue]
                  >"Francis Avila" <francisgavila@ yahoo.com> wrote in message[/color]
                  news:<vtsgvm4d0 dk157@corp.supe rnews.com>...[color=blue][color=green]
                  >> Matthew Sims wrote in message
                  >> <1e963607.03121 51408.583221e6@ posting.google. com>...[/color]
                  >
                  >Here's how the program basically worked. It's for a Tape Library with
                  >a robot arm in the middle. There are 40 slots and each is represented
                  >as an element in the array. If a tape was in one of the slots, that
                  >element # corresponds to the slot # and the tape ID would show in that
                  >element. All other elements represented blank slots. This allowed me
                  >to control the robot arm to the exact slot a tape resides since all I
                  >had to do was look at any elements that had tape IDs assigned.[/color]

                  Ah, I see. Well, that makes more sense. In this case it's *not* so
                  clear-cut whether to use a list or a dict (or whatever). A list is a
                  reasonable approach.

                  Right off the bat, I can think of a few:

                  - What you're doing now, but initializing an empty list to fixed length, eg,
                  tapearray = [None]*40. Now just use it (no need to worry about magically
                  extending the list as you add to random slots), but make sure you don't
                  modify the list with insert, append, extend, pop, etc., etc.: only perform
                  operations on its members.

                  Python doesn't do the implicit thing, so you're often well off by
                  preinitalizing data structures, as here. I simply say [None]*40 and your
                  entire original question disappears, because you were looking at the problem
                  in a perlish manner of "how do I use this array in a manner that doesn't
                  require me to declare its total size before I use it." Explicit is better
                  than implicit.

                  - Using a dict with integer keys. Because your tape array won't change in
                  size, and iterating over the whole thing looks to be the most common
                  operation (as opposed to random access), dict might not be the obvious
                  choice. But dicts are more flexable, and make explicit the importance of
                  the index. You don't need to initalize your dict because it will add
                  non-existent keys on assignment, but it's probably less of a hassle to do so
                  anyway, because it *will* raise a KeyError if you try to read a key it
                  doesn't have. To get around this, you need to subclass dict and make a
                  (commonly reimplemented) DefaultDict subclass, or make sure you consistently
                  use the setdefault method of your dict. I say just preinitalize the blasted
                  thing: tapearray = dict([(i, None) for i in range(40)]).

                  - Using a list of lists, with zeroth element of each sublist the slot
                  number. Now you don't have to worry about preinitalizing the list or
                  keeping the tape slots in order. I can't think of any advantage to this
                  approach, unless you need faster iteration with variable total length, and
                  don't need the slots to be ordered. Probably just use a dict.

                  - Write a TapeSlot class, a TapeArray class, and a TapeArrayVisito r class.
                  (I'm kidding! Don't do this.)

                  Of course, you can mix-and-match as your requirements demand. If slots need
                  more status information, you could use a dict of lists or a list of lists.
                  If slots have a set of operations proper to them, you can use a list of
                  TapeSlot objects; or you could wrap the interface to the tapearray in a
                  TapeArray class, and make slot access a hidden implementation detail.
                  [color=blue]
                  >So far the only way I could get this to work in Python was to insert
                  >"" to represent an empty slot. But Python counts "" when I want to see
                  >how many tapes are currently taking up slots "len(SLOTS) ". It would
                  >always show 40. So I now know that I need to write code to tell Python
                  >not to count "". Not too difficult.[/color]

                  Not at all:

                  len([tapeID for tapeID in tapearray if tapeID])

                  "If the item in tapearray is True (in a boolean context, '' is False) append
                  that item to a new list, then find the length of this new list."
                  [color=blue]
                  >
                  >I guess I'm realizing how I need to approach Python as my first OO.
                  >I'm re-writing the script as sort of a training. The program works
                  >flawlessly in Perl, I'm just doing it to learn. So far it has taken
                  >less lines of code in Python to perform the same tasks in Perl...up
                  >til this point. ;)[/color]

                  Unless you're doing relatively complex things that require a rich set of
                  data/semantics for tape slots and/or tape arrays, there's no reason to start
                  using objects to represent them: "Simple is better than complex." Some
                  people get drunk on OO. OO is useful, but can also add unnecessary
                  complexity and obscure what you're doing behind too many layers of
                  abstraction.

                  Finally, don't do line-of-code comparisons between Python and perl. Python
                  may be brief, but it is *not* terse, and will choose clarity over
                  more-magic-per-line. List comprehensions excepted. ;)

                  Ugh, I talk too much. Well, hope you like Python!
                  --
                  Francis Avila

                  Comment

                  • Peter Otten

                    #10
                    Re: Jumping around when assigning elements

                    Cameron Laird wrote:
                    [color=blue]
                    > We've probably convinced Mr. Sims that Python (and
                    > object-oriented programming) is really, really hard,
                    > particularly compared to Perl: we have to write
                    > hairy Class definitions just to do the simplest
                    > things.[/color]

                    Posting a piece of ugly code to meet a specification that is incomplete or
                    even wrong and at the same time showing Python in bad light compared to
                    Perl... I have to be more careful with my posts.

                    Peter

                    Comment

                    • Paul Rubin

                      #11
                      Re: Jumping around when assigning elements

                      matt@killermook ie.org (Matthew Sims) writes:[color=blue]
                      > For lists, I understand this:
                      > C=["need","some"," help"]
                      > print C[1]
                      > some
                      >
                      > But I can't seem to do this:
                      > C[3]="here"
                      >
                      > I know about C.append("here" ) but this brings me to my question...
                      >
                      > Is there anyway to assign to an element that wasn't defined in the
                      > beginning? Like if I wanted element 5 assigned but not element 4
                      > without using "" or None?[/color]

                      The simplest way is with a dictionary instead of a list:

                      D = {0:"need", 1:"some", 2:"help"}
                      print D[1]
                      some

                      Then you can do

                      D[3] = "here"
                      D[97] = "way over there"
                      D["banana"] = "yellow"

                      etc.

                      Comment

                      Working...