tl; dr slice
объекты генерируются интерпретатором, когда мы используем их в квадратных скобках, и разрешение их произвольности позволяет нам разрабатывать код, который их использует. Тем не менее, поскольку встроенный список для правильной работы полагается на indices()
, этот метод должен возвращать совместимые со списком значения (т. Е. Целые числа), а если он не может, он выдает ошибку.
Когда вы делаете
my_obj[1:3:2]
, интерпретатор по существу переводит его * как
my_obj.__getitem__(slice(1, 3, 2))
Это наиболее очевидно при использовании списков, которые имеют особое поведение, когда задаются фрагменты, но это поведение также есть другие типы данных в различных популярных библиотеках (например, numpy.array
и pandas.Dataframe
). Эти классы реализуют свои собственные __getitem__()
методы, которые имеют свои собственные особые способы обработки слайсов.
Теперь встроенный список предположительно использует slice.indices()
для разложения всего слайса на набор отдельных индексов, которые он может получить доступ, а затем сгруппировать и вернуться. Индексы списков могут быть только целыми числами, и они не хотят, чтобы эта функциональность нарушалась, поэтому наиболее последовательный способ go об этом - заставить slice.indices()
выдавать ошибку, когда он не может создать список целых чисел.
Они не могут ограничить slice
наличием только этих значений, поскольку это объект, созданный интерпретатором, который могут захотеть использовать другие пользовательские классы. Если вы проектируете объект, подобный этому:
class myGenerator:
def __getitem__(self, s): # s is a slice
def gen():
i = s.start
while i < s.stop:
yield i
i += s.step
return list(gen())
h = myGenerator()
print(h[1:4:.25])
# [1, 1.25, 1.5, 1.75, 2.0, 2.25, 2.5, 2.75, 3.0, 3.25, 3.5, 3.75]
print(h[0:1:0.1])
# [0, 0.1, 0.2, 0.30000000000000004, 0.4, 0.5, 0.6, 0.7, 0.7999999999999999, 0.8999999999999999, 0.9999999999999999]
, тогда он может выбрать нотацию среза, чтобы работать так, как ему хочется, поэтому мы можем установить для него пользовательское поведение. Но если бы мы изменили slice.indices()
, чтобы использовать это вместо этого, то это сломало бы встроенный list
- таким образом, python не позволяет нам.
* технически, для многих встроенных функций интерпретатор python может использовать ярлыки и выполнять жестко запрограммированные подпрограммы вместо того, чтобы фактически преобразовывать нотацию в вызовы функций и выполнять их. Но для наших целей аналогия работает достаточно хорошо, поскольку она делает это для пользовательских объектов.