>>> a = [1, 2, 3, 4, 5]
>>> a[::2] # iterate over the whole list in 2-increments
[1, 3, 5]The special case x[::-1] is a useful idiom for 'x reversed'.
>>> a[::-1]
[5, 4, 3, 2, 1]Python's advanced slicing operation has a barely known syntax element, the ellipsis.
>>> class C(object):
... def __getitem__(self, item):
... return item
...
>>> C()[1:2, ..., 3]
(slice(1, 2, None), Ellipsis, 3)>>> a = range(10)
>>> a
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> a[:5] = [42]
>>> a
[42, 5, 6, 7, 8, 9]
>>> a[:1] = range(5)
>>> a
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> del a[::2]
>>> a
[1, 3, 5, 7, 9]
>>> a[::2] = a[::-2]
>>> a
[9, 3, 5, 7, 1]Note: when assigning to extended slices (s[start:stop:step]), the assigned iterable must have the same length as the slice.
>>> x = [1, 2, 3]
>>> y = x[:]
>>> y.pop()
3
>>> y
[1, 2]
>>> x
[1, 2, 3]>>> x = [1, 2, 3]
>>> y = x
>>> y[:] = [4, 5, 6]
>>> x
[4, 5, 6]This Sieve of Eratosthenes produces a list that has either the prime number or 0. Elements are 0'd out with the slice assignment in the loop.
>>> def eras(n):
... last = n + 1
... sieve = [0,0] + list(range(2, last))
... sqn = int(round(n ** 0.5))
... it = (i for i in xrange(2, sqn + 1) if sieve[i])
... for i in it:
... sieve[i*i:last:i] = [0] * (n//i - i + 1)
... return filter(None, sieve)
>>> eras(5)
[2, 3, 5]To work, the slice on the left must be assigned a list on the right of the same length.
>>> [(i,j) for i in range(3) for j in range(i)]
[(1, 0), (2, 0), (2, 1)]
>>> list((i,j) for i in range(3) for j in range(i))
[(1, 0), (2, 0), (2, 1)]The example is form the Udacity course 'Design of Computer Programs' with instructor Peter Norvig.
>>> import itertools>>> def imright(h1, h2):
... "House h1 is immediately right of h2 if h1-h2 == 1."
... return h1-h2 == 1>>> def nextto(h1, h2):
... "Two houses are next to each other if they differ by 1."
... return abs(h1-h2) == 1>>> def zebra_puzzle():
... "Return a tuple (WATER, ZEBRA indicating their house numbers."
... houses = first, _, middle, _, _ = [1, 2, 3, 4, 5]
... orderings = list(itertools.permutations(houses)) # 1
... return next((WATER, ZEBRA)
... for (red, green, ivory, yellow, blue) in orderings
... if imright(green, ivory)
... for (Englishman, Spaniard, Ukranian, Japanese, Norwegian) in orderings
... if Englishman is red
... if Norwegian is first
... if nextto(Norwegian, blue)
... for (coffee, tea, milk, oj, WATER) in orderings
... if coffee is green
... if Ukranian is tea
... if milk is middle
... for (OldGold, Kools, Chesterfields, LuckyStrike, Parliaments) in orderings
... if Kools is yellow
... if LuckyStrike is oj
... if Japanese is Parliaments
... for (dog, snails, fox, horse, ZEBRA) in orderings
... if Spaniard is dog
... if OldGold is snails
... if nextto(Chesterfields, fox)
... if nextto(Kools, horse)
... )>>> zebra_puzzle()
(1, 5)Wrap an iterable with enumerate and it will yield the item along with its index.
>>> a = ['a', 'b', 'c', 'd', 'e']
>>> for index, item in enumerate(a): print index, item
...
0 a
1 b
2 c
3 d
4 eenumerate has partly been covered in this answer, but recently I've found an even more hidden feature of enumerate that I think deserves its own post instead of just a comment.
Since Python 2.6, you can specify a starting index to enumerate in its second argument:
>>> l = ['spam', 'ham', 'eggs']
>>> list(enumerate(l))
[(0, 'spam'), (1, 'ham'), (2, 'eggs')]
>>> list(enumerate(l, 1))
[(1, 'spam'), (2, 'ham'), (3, 'eggs')]>>> 'xyz' * 3
'xyzxyzxyz'>>> [1, 2] * 3
[1, 2, 1, 2, 1, 2]>>> (1, 2) * 3
(1, 2, 1, 2, 1, 2)We get the same result with reflected (swapped) operands
>>> 3 * 'xyz'
'xyzxyzxyz'It works like this:
>>> s = 'xyz'
>>> num = 3To evaluate an expression s * num interpreter calls s.__mul__(num)
>>> s * num
'xyzxyzxyz'>>> s.__mul__(num)
'xyzxyzxyz'To evaluate an expression num * s interpreter calls num.__mul__(s)
>>> num * s
'xyzxyzxyz'>>> num.__mul__(s)
NotImplementedIf the call returns NotImplemented then interpreter calls a reflected operation s.__rmul__(num) if operands have different types
>>> s.__rmul__(num)
'xyzxyzxyz'We can override the __mul__ method
>>> class MyList(list):
... def __mul__(self, n):
... result = [l * n for l in self]
... return result if 0 <= n else list(reversed(result))
>>> l = MyList([1, 2, 3])
>>> l * 2
[2, 4, 6]
>>> l * -2
[-6, -4, -2]>>> a = [1,2]
>>> a.append(a)
>>> a
[1, 2, [...]]
>>> a[2]
[1, 2, [...]]
>>> a[2][2][2][2][2][2][2][2][2] == a
TrueThe signature of iter is iter(callable, sentinel) -> iterator. If a second argument, sentinel, is given to iter(), the first argument must be a callable. The created iterator will call the callable on each call to its next() method, until the callabele return value equal to the sentinel.
>>> import StringIO
>>> fp = StringIO.StringIO('''1
... 2
... end
... 3
... ''')
>>> for line in iter(lambda: fp.readline().strip(), 'end'):
... print line.strip()
1
2>>> def to_list(gen):
... return list(gen)>>> to_list(((i,j) for i in range(3) for j in range(i)))
[(1, 0), (2, 0), (2, 1)]Is the same as:
>>> to_list((i,j) for i in range(3) for j in range(i))
[(1, 0), (2, 0), (2, 1)]