[Tutor] changing list index start

Lie Ryan lie.1296 at gmail.com
Sat Sep 11 18:00:02 CEST 2010

On 09/11/10 23:25, Rance Hall wrote:
> On Fri, Sep 10, 2010 at 6:14 PM, Lie Ryan <lie.1296 at gmail.com> wrote:
>> On 09/11/10 07:36, Rance Hall wrote:
> <snip>
>> In most cases in Python, you would almost never need to reference the
>> list's index directly since python makes it easy to use iterators;
>> however in your particular case, which is a valid exception, enumerate()
>> takes an optional second argument `start` which defines the number that
>> enumerate start to count with, i.e. you can do:
>> for i, option in enumerate(mainmenuoptions, 1):
>>    print('%s. %s' % (i, option))
>>> php provided a way to change this, but I can find no documentation
>>> that says python can do this as well.
> Thanks everyone for responding,  Because this menu structure is
> repeated many times in my code, the ideal solution would have been to
> "set index start = 1" in the beginning of the script.

That would produce a catastrophic effect. What would happen to standard
library modules or external modules now that they have to work in a
different base?

> something like sysctl variables in Linux perhaps but in this case only
> valid for this program.
> Its clear from the responses that this solution is not available in
> python, I wish it were, it would make my life much easier for this
> project.

Personally I think it's a bad idea. Being able to globally rebase list
index would triple the code's WTF count.

> I like the approach that Lie suggested, as it seems more "natural
> python" to me as opposed to a workaround.
> However this is also only half a solution since it applies to the
> printed menus only and not to the response afterward.
> It seems that Luke is right looks like we have to do math with the indexes.
> Lie also referred to my particular case as a valid exception, are
> there enough other such valid exceptions that requesting a feature
> enhancement would gain some traction?

When I mean, a valid exception, it's referring to "knowing the index
number" of a list, not to the ability of changing the list's base.

> If this is but one of a few special cases, I doubt it would be worth
> the time or trouble to formally make the request.

As an alternative solution, you can derive from UserList and overload
the __getitem__ and __setitem__ operator:

from UserList import UserList
class RebasedList(UserList):
    def __init__(self, base=1, *args, **kwargs):
        UserList.__init__(self, *args, **kwargs)
        self.base = base
    def __getitem__(self, index):
        if self.base <= index < self.base + len(self):
            return UserList.__getitem__(self, index - self.base)
            raise IndexError(
                "RebasedList index out of range [%s-%s), "
                "given index %s" %
                (self.base, self.base+len(self), index))
    def __setitem__(self, index, item):
        if self.base <= index < self.base + len(self):
            return UserList.__setitem__(self, index - self.base, item)
            raise IndexError(
                "RebasedList assignment index out of range [%s-%s), "
                "given index %s" %
                (self.base, self.base+len(self), index))
    # for complete emulation, you will also need to override:
    # __iter__, __delitem__, __getslice__, __setslice__,
    # __delslice__, __add__, __mul__, index, insert, pop,
    # remove, and possibly others

You can use it like this:

rl = RebasedList(10, [3, 1, 2, 4, 2, 1]
rl[10] # rl[0]
rl[11] = 29 # rl[1] = 29
print rl # [3, 29, 2, 4, 2, 1]

Then there is the case that negative index no longer work cleanly with a
custom list base.

> Maybe I should ask if there is a better way to do what I want to do
> here. Is there?

More information about the Tutor mailing list