changing the List's behaviour?

M

meinrad recheis

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
 
B

Ben Finney

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

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.
i want to change the List so that it returns None if the index for
accesssing list elements is out of bound.

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

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)?
 
T

Terry Reedy

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==None).

Terry J. Reedy
 
P

Peter Otten

meinrad said:
i want to change the List so that it returns None if the index for
accesssing list elements
is out of bound.

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

class DefaultList(list):
def __init__(self, sequence=[], default=None):
list.__init__(self, sequence)
self.default = default
def __getitem__(self, index):
try:
return list.__getitem__(self, index)
except IndexError:
return self.default

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

theList = DefaultList(default="X")
print theList[1]
 
P

Peter Otten

Heather said:
class DefaultList(list):
def __init__(self, sequence=[], default=None):
list.init(self, sequence)
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 = [ ]
list.__init__(self, sequence)

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
 
H

Heather Coppersmith

Heather said:
class DefaultList(list):
def __init__(self, sequence=[], default=None):
list.init(self, sequence)

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 = [ ]
list.__init__(self, sequence)
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?

Oops, my mistake. ;-)

Regards,
Heather
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,576
Members
45,054
Latest member
LucyCarper

Latest Threads

Top