Когда и как использовать `slice (obj)` для типов не `int` / `None`? - PullRequest
0 голосов
/ 25 октября 2018

В Python 3 следующий код не выдает ошибку:

slice(10.0)

, а следующее:

range(10.0)

Если я пытаюсь использовать объект slice(float),также произойдет сбой:

list(range(20))[slice(10.0)]

со следующей ошибкой:

TypeError: slice indices must be integers or None or have an __index__ method

, указывающий, что slice() может использоваться с некоторымидругой объект, реализующий метод __index__.

Когда / как использовать slice(obj) для не int / None типов?

Почему допускается использование чисел floatиспользуется при создании объекта slice()?Могу ли я полагаться на slice(float)slice(float, float) и slice(float, float, float)), никогда не жаловавшиеся на создание экземпляров в Python 3?

РЕДАКТИРОВАТЬ:

Это, похоже, связано с PEP357 https://docs.python.org/2.5/whatsnew/pep-357.html

Однако мне неясно, имеет ли это другие применения помимо реализации расширенного индексирования в NumPy.

EDIT3: EDIT2 в основном содержал вторую частьпринятый ответ с некоторой синтаксической ошибкой, поэтому он был удален

1 Ответ

0 голосов
/ 25 октября 2018

Да, вы можете передавать объекты любого типа slice.Документация не упоминает об ограничениях для типа аргументов среза, а исходный код для конструктора среза говорит только о том, что «start, stop и step являются объектами python».

list(range(20))[slice(10.0)] отклоняет объект слайса с аргументами с плавающей точкой, но это, похоже, относится к типу списка.Сама модель данных не выполняет неявную проверку типов перед вызовом __getitem__.Вы можете написать свой собственный класс, который принимает больше нетрадиционных срезов.Пример:

>>> class Fred:
...     def __getitem__(self, idx):
...         return "baz"
...
>>> x = Fred()
>>> print(x[slice("Foo", "Bar")])
baz
>>> print(x[1.0: -10.5])
baz

Что касается того, есть ли практическая практическая причина разрешить нецелые срезы, ни один не приходит на ум ... Но у сообщества Python есть культурная норма "мы"все взрослые здесь ".То есть что-то не должно быть запрещено только потому, что для этого нет очевидного практического применения.Если кто-то хочет сделать что-то, что кажется глупым, то при прочих равных условиях мы должны позволить ему.


Мы установили, что определяемые пользователем типы могут принимать любые виды фрагментов, которые они хотят.Но что, если вы хотите иметь возможность нарезать встроенные типы необычными срезами?Вы не можете изменить реализацию типа списка, чтобы удалить проверку типа, которую он делает.__index__ пригодится как способ определения новых типов, которые можно использовать для нарезки списков.Например,

>>> class Begin:
...     def __index__(self):
...         return 0
...
>>> class End:
...     def __index__(self):
...         return -1
...
>>> list(range(20))[slice(Begin(), End())]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18]
...