[Tutor] Two questions [array out of bounds / lazylist / autovivification]

Danny Yoo dyoo@hkn.eecs.berkeley.edu
Sun, 14 Apr 2002 01:16:09 -0700 (PDT)


On Sat, 13 Apr 2002, Lloyd Kvam wrote:

> That will teach me to post without checking!
>
> The list assignment does not let you assign beyond the existing
> size of a list.  It prevents:
> 	alist = []
> 	alist[5] = 'hi'

Yes; this is one difference between Python and Perl --- Python assumes
that if we index beyond the length of an array, we probably goofed, and
should be told about the error through an IndexError.  On the other hand,
Perl will automatically expand the array to the appropriate size.  In Perl
terms, it "autovivifies" array elements.


It is possible to write a "lazylist", that is, a list subclass that
supports autovivification.  Here's one way to do it:


###
class lazylist(list):
    def __getitem__(self, i):
        if not (type(i) is tuple):
            self.padExpand(i)
        return list.__getitem__(self, i)

    def __setitem__(self, i, obj):
        if not (type(i) is tuple):
            self.padExpand(i)
        return list.__setitem__(self, i, obj)

    def padExpand(self, i):
        """Make sure that this list contains n+1 elements by padding
        None at the end."""
        if i < 0: return
        if len(self) <= i:
            self.extend([None] * (i - len(self) + 1))
###


Let's take a look!

###
>>> l = lazylist([1, 2, 3])
>>> l
[1, 2, 3]
>>> l[10:]
[]
>>> l
[1, 2, 3]
>>> l[10]
>>> l
[1, 2, 3, None, None, None, None, None, None, None, None]
>>> l[20] = "twenty"
>>> l
[1, 2, 3, None, None, None, None, None, None, None, None, None, None,
 None, None, None, None, None, None, None, 'twenty']
###



As a caveat: I'm not sure if this is a good idea or not to use lazylist.
Autovivification has some really serious potential of hiding off-by-one
boundary errors, and that's a bad thing.  I think the intention of the
IndexError is to force programmers to really think about boundary cases,
instead of just shoving everything underneath the rug.


Hope this helps!