changing the List's behaviour?

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • meinrad recheis

    changing the List's behaviour?

    hi pythoneers

    i am very annoyed by the List's index out of bouds exception
    it forces me to complicate my code by adding length checking

    i might be spoilt by Ruby which returns nil for not existing indices.
    i want to change the List so that it returns None if the index for
    accesssing list elements
    is out of bound.

    i am not very experienced in python, so i ask you for suggestions.

    thanks in advance,
    Meinrad Recheis



  • Ben Finney

    #2
    Re: changing the List's behaviour?

    On Sun, 27 Jul 2003 22:41:43 +0200, meinrad recheis wrote:[color=blue]
    > i am very annoyed by the List's index out of bouds exception
    > it forces me to complicate my code by adding length checking[/color]

    No, it forces you to ensure your code doesn't try to access a
    non-existent list element.

    Or, it forces you to catch the exception and deal with it.
    [color=blue]
    > i want to change the List so that it returns None if the index for
    > accesssing list elements is out of bound.[/color]

    This would prevent you from distinguishing between "the index was out of
    range" and "the element at that index is the None object".
    [color=blue]
    > i am not very experienced in python, so i ask you for suggestions.[/color]

    Take a good look at the code that is accessing non-existent index
    values. Why is it doing so? Do you really want a list (ordered
    collection, with a fixed set of keys) or are there cases where you want
    a dict (unordered collection, arbitrary set of keys)?

    --
    \ "I know you believe you understood what you think I said, but I |
    `\ am not sure you realize that what you heard is not what I |
    _o__) meant." -- Robert J. McCloskey |
    Ben Finney <http://bignose.squidly .org/>

    Comment

    • Terry Reedy

      #3
      Re: changing the List's behaviour?

      [color=blue][color=green]
      > > i want to change the List so that it returns None if the index for
      > > accesssing list elements is out of bound.[/color][/color]

      Slicing always 'works' (does not raise exception), so seq[i:i+1]
      returns empty slice rather than length 1 slice if i too large. This
      is a standard idiom for getting, for instance, first element of list
      if there is one when there might not be.

      So slice and condition off length and if 1, extract element. This has
      advantage over idea above that [] is different from [None] (which you
      would get is seq[i]==None).

      Terry J. Reedy


      Comment

      • Peter Otten

        #4
        Re: changing the List's behaviour?

        meinrad recheis wrote:
        [color=blue]
        > i want to change the List so that it returns None if the index for
        > accesssing list elements
        > is out of bound.[/color]

        If you really need it, you can write a class similar to the one below:

        class DefaultList(lis t):
        def __init__(self, sequence=[], default=None):
        list.__init__(s elf, sequence)
        self.default = default
        def __getitem__(sel f, index):
        try:
        return list.__getitem_ _(self, index)
        except IndexError:
        return self.default

        if __name__ == "__main__":
        theList = DefaultList("ab c", "?")
        print theList[1]
        print theList[99]

        theList = DefaultList(def ault="X")
        print theList[1]


        Comment

        • Peter Otten

          #5
          Re: changing the List's behaviour?

          Heather Coppersmith wrote:
          [color=blue][color=green]
          >> class DefaultList(lis t):
          >> def __init__(self, sequence=[], default=None):[/color][/color]
          list.init(self, sequence)[color=blue]
          >
          > That's asking for trouble. That mutable default argument for
          > sequence is evaluated at class definition-time, and all instances
          > of DefaultList created without a sequence argument will end up
          > sharing one list.
          >
          > Do this instead:
          >
          > class DefaultList( list ):
          > def __init__( self, sequence = None, default = None ):
          > if sequence is None:
          > sequence = [ ]
          >[color=green]
          >> list.__init__(s elf, sequence)[/color][/color]

          I can see the trouble only if the sequence argument is used to initialize a
          member, e.g.

          def __init__(self, seq=[]):
          self.seq = seq # bad, multiple instances may share one list

          However, in the DefaultList case, sequence is never changed.
          So I don't see what can go wrong. Am I overlooking something?

          - Peter

          Comment

          • Heather Coppersmith

            #6
            Re: changing the List's behaviour?

            On Wed, 30 Jul 2003 17:36:12 +0200,
            Peter Otten <__peter__@web. de> wrote:
            [color=blue]
            > Heather Coppersmith wrote:[color=green][color=darkred]
            >>> class DefaultList(lis t):
            >>> def __init__(self, sequence=[], default=None):[/color][/color]
            > list.init(self, sequence)[color=green]
            >>
            >> That's asking for trouble. That mutable default argument for
            >> sequence is evaluated at class definition-time, and all instances
            >> of DefaultList created without a sequence argument will end up
            >> sharing one list.
            >>
            >> Do this instead:
            >>
            >> class DefaultList( list ):
            >> def __init__( self, sequence = None, default = None ):
            >> if sequence is None:
            >> sequence = [ ]
            >>[color=darkred]
            >>> list.__init__(s elf, sequence)[/color][/color][/color]
            [color=blue]
            > I can see the trouble only if the sequence argument is used to initialize a
            > member, e.g.[/color]
            [color=blue]
            > def __init__(self, seq=[]):
            > self.seq = seq # bad, multiple instances may share one list[/color]
            [color=blue]
            > However, in the DefaultList case, sequence is never changed.
            > So I don't see what can go wrong. Am I overlooking something?[/color]
            [color=blue]
            > - Peter[/color]

            Oops, my mistake. ;-)

            Regards,
            Heather

            --
            Heather Coppersmith
            That's not right; that's not even wrong. -- Wolfgang Pauli

            Comment

            Working...