Как использовать встроенную функцию slice
и как ее использовать?
Я знаю, как прямая дорога питонской нарезки - l1[start:stop:step]
. Я хочу знать, есть ли у меня объект среза, тогда как его использовать?
Python slice how-to, я знаю кусочек Python, но как я могу использовать для этого встроенный объект slice?
Ответ 1
Вы создаете срез, вызывая срез с теми же полями, которые вы использовали бы при записи [start: end: step]:
sl = slice(0,4)
Чтобы использовать срез, просто передайте его, как если бы он был индексом в список или строку:
>>> s = "ABCDEFGHIJKL"
>>> sl = slice(0,4)
>>> print(s[sl])
'ABCD'
Скажем, у вас есть файл текстовых полей фиксированной длины. Вы можете определить список срезов, чтобы легко извлекать значения из каждой "записи" в этом файле.
data = """\
0010GEORGE JETSON 12345 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""".splitlines()
fieldslices = [slice(*fielddef) for fielddef in [
(0,4), (4, 21), (21,42), (42,56), (56,58),
]]
fields = "id name address city state".split()
for rec in data:
for field,sl in zip(fields, fieldslices):
print("{} : {}".format(field, rec[sl]))
print('')
Печать
id : 0010
name : GEORGE JETSON
address : 12345 SPACESHIP ST
city : HOUSTON
state : TX
id : 0020
name : WILE E COYOTE
address : 312 ACME BLVD
city : TUCSON
state : AZ
id : 0030
name : FRED FLINTSTONE
address : 246 GRANITE LANE
city : BEDROCK
state : CA
id : 0040
name : JONNY QUEST
address : 31416 SCIENCE AVE
city : PALO ALTO
state : CA
Ответ 2
Квадратные скобки после последовательности обозначают либо индексацию, либо нарезку в зависимости от того, что внутри скобок:
>>> "Python rocks"[1] # index
'y'
>>> "Python rocks"[1:10:2] # slice
'yhnrc'
Оба этих случая обрабатываются методом __getitem__()
последовательности (или __setitem__()
, если слева от знака равенства). Индекс или срез передается методам в виде единственного аргумента, и способ Python делает это путем преобразования нотации среза (1:10:2
в этом случае) в объект среза: slice(1,10,2)
.
Итак, если вы определяете свой собственный подобный последовательности класс или переопределяете методы __getitem__
или __setitem__
или __delitem__
другого класса, вам нужно проверить аргумент индекса, чтобы определить, является ли это int
или slice
и обрабатывать соответственно:
def __getitem__(self, index):
if isinstance(index, int):
... # process index as an integer
elif isinstance(index, slice):
start, stop, step = index.indices(len(self)) # index is a slice
... # process slice
else:
raise TypeError("index must be int or slice")
Объект A slice
имеет три атрибута: start
, stop
и step
, а один метод: indices
, который принимает один аргумент, длину объекта и возвращает 3-кортеж: (start, stop, step)
.
Ответ 3
>>> class sl:
... def __getitem__(self, *keys): print keys
...
>>> s = sl()
>>> s[1:3:5]
(slice(1, 3, 5),)
>>> s[1:2:3, 1, 4:5]
((slice(1, 2, 3), 1, slice(4, 5, None)),)
>>>
Ответ 4
Функция slice
возвращает объекты среза. Объекты среза являются одним из внутренних типов Python, которые оптимизированы для производительности чтения - все их атрибуты доступны только для чтения.
Изменение slice
может быть полезно, если вы хотите изменить поведение по умолчанию. Например, lxml
использует нотацию фрагментов для доступа к элементам DOM (однако я не подтвердил, как они это сделали).
Ответ 5
Пытаясь ответить на подмножество строки, основанной на переменной, я вспомнил, что у numpy есть синтаксически хороший способ определения объектов срезов:
>>> import numpy as np
>>> s = "The long-string instrument is a musical instrument in which the string is of such a length that the fundamental transverse wave is below what a person can hear as a tone."
>>> z = np.s_[18:26] # in this case same as slice(18, 26, None)
>>> s[z]
'strument'
Решаемая здесь проблема заключается в том, как сохранить срез в переменной для последующего использования, и np.s_
позволяет это сделать. Да, он не является встроенным, но поскольку этот оригинальный вопрос был перенаправлен сюда, я чувствую, что мой ответ также относится и к этому. Кроме того, numpy был одной из причин, по которой в Python, IIRC были добавлены столь продвинутые возможности нарезки.
Пример более сложной "нарезки":
>>> data = np.array(range(6)).reshape((2, 3))
>>> z = np.s_[:1, 1:2]
>>> data[z]
array([[1]])
>>> data
array([[0, 1, 2],
[3, 4, 5]])
>>> z
(slice(None, 1, None), slice(1, 2, None))
где z теперь кортеж кусочков.