RSS Feed
Download our iPhone app
Browse DevX
Sign up for e-mail newsletters from DevX


The Python 2.5 Goodie Bag: Language Enhancements and Modules : Page 2

The 2.5 version of Python offered lots of useful enhancements. In this article, you'll learn about some specific modules, as well as performance improvements, that are likely to bring big smiles to the faces of many Python developers.

The '__index__' Method
Slicing is an operation performed on sequences that allows you to extract a subset of the element. The syntax is: sequence[start:stop:step]. 'start' is mandatory, 'stop' defaults to the end of the sequence, and 'step' defaults to 1. When you slice a sequence, Python starts from the start index and returns another sequence (same type as original) that contains all the elements between 'start' and 'stop' in increments of 'step'.

You can use a negative number to count from the end of the sequence too. The step may also be negative, but in this case the start index must be bigger than the stop index resulting in a reverse slice. This used to be the only way to reverse a sequence before the reversed() built-in function was introduced in Python 2.4 (yes, you get some history for the same price).

Now let's break some bread and slice it too.

# prepare a list called bread with 10 integers 
bread = range(1,11)
print bread

# plain slice
print bread[1:10:2]

# slice using negative indices
print bread[-9:-7]

# old way of reversing a sequence
print bread[::-1]

[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
[2, 4, 6, 8, 10]
[2, 3]
[10, 9, 8, 7, 6, 5, 4, 3, 2, 1]
The indices for start, stop, and step used to be integers or long integers only. This is fine for almost everybody. Why would you want to index into a collection using a different type? You wouldn't. After all, the meaning of an index is a specific location inside the sequence, and locations are always integers. However, NumPy, which is the leading Python scientific computing package, requires it. NumPy is a Python extension that provides a lightning fast multi-dimensional array and various functions, linear algebra operations, and transformations to act on it.

I can hear you thinking: "What's the big deal about arrays? Didn't we have them back in the day in BASIC for the Dragon32?". Well, you didn't have THAT kind of array. Multi-dimensional arrays (tensors) are a crucial building block for many scientific computations. NumPy is a very important and influential package that single-handedly made Python a great success in the scientific community. As evidence of its importance, NumPy is slated for inclusion in the standard Python library at some point.

NumPy uses its own data types (remember the ctypes data types?) to represent integers with higher fidelity than Python's native int and long. These types were not usable for slicing, which is very common in NumPy. The most viable solution was to allow arbitrary types to be used as slicing indices if they define an __index__ method whose return value is int or long. In the following code I defined a few classes with __index__ methods that I use to dice and slice a poor 'bread.'

class One(object):
    def __index__(self):
        return 1

class Two(object):
    def __index__(self):
        return 2

class Ten(object):
    def __index__(self):
        return 10

print bread[One():Ten():Two()]

one = One()
two = Two()
ten = Ten()
print x[one:ten:two]

[2, 4, 6, 8, 10]
[2, 4, 6, 8, 10]

Close Icon
Thanks for your registration, follow us on our social networks to keep up-to-date