Python has a very easy and powerful slicing syntax:
>>> s = "Python rocks!"
First six elements:
>>> s[:6]
'Python'
Last six elements:
>>> s[-6:]
'rocks!'
Every other element:
>>> s[::2]
'Pto ok!'
Reverse elements:
>>> s[::-1]
'!skcor nohtyP'
In general, we can index a sequence by index:
>>> s[index]
Or slice:
>>> s[start:stop:step]
(where each slice parameter is optional)
Let's define a class to see what gets passed when we get an item:
class Foo(object):
def __getitem__(self, item):
return item
>>> f = Foo()
>>> f["key"]
'key'
>>> f[2]
2
>>> f[1:10:3]
slice(1, 10, 3)
>>> f[3:-6]
slice(3, -6, None)
>>> f[:]
slice(None, None, None)
What is this slice
object?
The representaion tells you how to create a slice
object:
>>> a = list(range(10))
>>> s = slice(1, 10, 3)
>>> a[s]
[1, 4, 7]
Let's look at the attributes:
>>> s.start
1
>>> s.stop
10
>>> s.step
3
>>> s.step = 2
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: readonly attribute
>>> hash(s)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'slice'
Slice objects are immutable, but not hashable!
Assuming it was hashable, we could write:
>>> d = dict()
>>> s = slice(1, 5)
>>> d[s] = 42 # will actually raise a TypeError
>>> d[1:5]
42
This would be confusing, as a dict is not a sequence!
On the other hand, assuming the slice object would be mutable:
>>> a = "Python"
>>> s = slice(2, 4)
>>> a[s]
'th'
>>> s.start = 0 # will actually raise an AttributeError
>>> a[s]
'Pyth'
Less, confusing. As there is no practical usecase for either, I assume that Guido did not want to leave any room for confusion.
Or as Tim Peters would say:
Special cases aren't special enough to break the rules.
Although practicality beats purity.
data = """\
0010George Jetson 1245 Spaceship St Houston TX
0020Wile E Coyote 312 Acme Blvd Tucson AZ
0030Fred Flintstone 246 Granite Lane Bedrock CA
0040Jonny Quest 31416 Science AVE Palo Alto CA
0050Anne Costello 326 Michigan Rd Round Rock TX
0060Robert Morrison 125 Hyndford St Grand Island NE
""".splitlines()
fields = [
('id', slice( 0, 4)),
('name', slice( 4, 21)),
('address', slice(21, 42)),
('city', slice(42, 56)),
('state', slice(56, 58)),
]
for record in data:
for field, sl in fields:
print("%s: %s" % (field, record[sl]))
print()
.indices()
S.indices(len) -> (start, stop, stride)
Assuming a sequence of length len, calculate the start and stop
indices, and the stride length of the extended slice described by
S. Out of bounds indices are clipped in a manner consistent with the
handling of normal slices.
Allows you to easily create your own loops over indices:
class Loopy(object):
def __init__(self, length):
self.length = length
def __getitem__(self, item):
if isinstance(item, slice):
for i in range(*item.indices(self.length)):
yield i
...
Python had slicing:
Python 1.0.1
Copyright 1991-1994 Stichting Mathematisch Centrum, Amsterdam
>>> s = "Python"
>>> s[1:-2]
'yth'
>>> s[::-1]
File "<stdin>", line 1
s[::-1]
^
SyntaxError: invalid syntax
But:
No slice object
Only start
and stop
argument
There was no third step
(or stride
) argument
From the release notes:
Changes for use with Numerical Python: builtin function slice() and
Ellipses object, and corresponding syntax:
x[lo:hi:stride] == x[slice(lo, hi, stride)]
x[a, ..., z] == x[(a, Ellipses, z)]
Great:
slice
and Ellipsis
objects added by Jim Hugunin and Chris Chase
the third slicing step
argument was add to the syntax:
A[1:10:2], A[:-1:1], A[::-1]
But:
Michael Hudson submitted a patch for Python’s built-in list, tuple,
and string sequence types to support the step
argument:
>>> s = "Python"
>>> s[::-1]
'nohtyP'
Normally users of Python don't have to deal with slice objects much, even though they use them all the time.
They become important when writing libraries which support Python's slicing syntax to access arrays. For example: array, bitarray and in particular:
For example 2 dimensional array:
>>> from numpy import array
>>> a = array([[1, 2, 3],
... [4, 5, 6],
... [7, 8, 9]])
>>> a[2, 1]
8
>>> a[0, 1:]
array([2, 3])
>>> a[:-1, :-1]
array([[1, 2],
[4, 5]])
Numpy's s_
, a nicer way to build up index tuples for arrays:
>>> from numpy import s_
>>> s_[1::-2]
slice(1, None, -2)
>>> s_[1, ::-1, ..., 1:-1:3]
(1, slice(None, None, -1), Ellipsis, slice(1, -1, 3))
We can simplify our earlier example:
fields = [
('id', s_[:4]),
('name', s_[4:21]),
('address', s_[21:42]),
('city', s_[42:56]),
('state', s_[56:58]),
]
Table of Contents | t |
---|---|
Exposé | ESC |
Presenter View | p |
Source Files | s |
Slide Numbers | n |
Toggle screen blanking | b |
Show/hide next slide | c |
Notes | 2 |
Help | h |