When you've been using a programming language for a long time, you like to think that syntax-wise, it has no more secrets left for you.

Today I was proven wrong and found out about Python's extended slice assignment, which is present since Python 2.3.5.

While looking for ways to speed-up my basic implementation of the Sieve of Eratosthenes I stumbled upon the following snippet:

def eras(n):
  siv=range(n+1)
  siv[1]=0
  sqn=int(round(n**0.5))
  for i in range(2,sqn+1):
    if siv[i]!=0:
        siv[2*i:n/i*i+1:i]=[0]*(n/i-1)
  return filter(None,siv)

While this code does more or less the same thing as my sieve code, I was puzzled about line 7. This syntax was new to me.

I knew about the step argument for slices, making things like getting all even numbers from a range as easy as:

>>> L = range(10)
>>> L[::2]
[0, 2, 4, 6, 8]

What I didn't know, is that you can assign an equal-length sequence to the slice and have it replace those values, given that the sequence is mutable (eg. a list) like this:

>>> L = range(10)
>>> L[::2] = ['x','x','x','x','x']
>>> L
['x', 1, 'x', 3, 'x', 5, 'x', 7, 'x', 9]

Now that's a useful trick to know if you didn't already!

One of the reasons the above mentioned sieve was so much faster than mine, is that by clever use of the extended slice assignment syntax, the crossing-off of multiples is done with one assignment instead of many in a loop.

blog comments powered by Disqus