2016-09-11 2 views
6

Я только улучшение тестового покрытия для library, который должен поддерживать ломтики, и я заметил, что ломтики могут содержать нецелые типы:Почему в кусочках python допускаются не встроенные встроенные типы?

>>> slice(1, "2", 3.0) 
slice(1, '2', 3.0) 
>>> sl = slice(1, "2", 3.0) 
>>> [1,2,3][sl] 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
TypeError: slice indices must be integers or None or have an __index__ method 

Это может быть просто моя статической типизацией фона, но это, кажется, странно для меня, что встроенные типы без __index__ могут быть переданы здесь без TypeError. Почему это так? Был бы я прав, если предположить, что произвольные типы разрешены для поддержки печати уток для типов, которые реализуют __index__? Является ли отсутствие проверки типа из-за причин производительности для наиболее часто используемых случаев?

До PEP 357 был ли этот фрагмент недействительным?

+0

Синтаксис среза с поплавками может эффективно описывать ограничительную рамку в n-мерном пространстве, что может быть удобно в некоторых случаях. Пользовательский тип может принимать такие срезы. – Kevin

+0

Это действительно интересный прецедент для плавания, о котором я не думал. Почему строки разрешены? – shuttle87

+1

Вы также можете использовать [Эллипсис] (http://stackoverflow.com/questions/772124/what-does-the-python-ellipsis-object-do) в срезах. –

ответ

2

Был ли я прав, если предположить, что произвольные типы разрешены для поддержки печати утинов для типов, которые реализуют __index__?

Нет фактической причины, по которой следует ограничивать типы, переданные при инициализации объектов slice. Точно так же, как указано в рациональном для PEP 357, numpy и числовых типах, которые он использует, не может наследовать от объекта, поэтому строгие issubclass проверки пройденного типа сделают их непригодными для использования в качестве значений индекса. Таким образом, применяется утиная типизация, если она определяет соответствующий метод (__index__), его можно использовать.

Также обратите внимание, что это (присутствие __index__) обеспечивается только при применении ломтик (как вы видели, TypeError был поднят во время __getitem__, т.е. list_subscript) операции, когда PySlice_GetIndicesEx называется, чтобы попытаться получить значения, которые вы прошло.

slice objects initializer не делает никакой дискриминации на какой тип он принимает все PyObject «s можно применить как можно видеть из его подписи:

PyObject * 
PySlice_New(PyObject *start, PyObject *stop, PyObject *step) 
{ 
    /* rest omitted */ 

До PEP 357 был срез в примере недействительным?

Я только что построил версию Python 2.4 и протестировали его (PEP 357 появился в 2.5, если я не ошибаюсь), снова чек, если аргументы являются числовыми не делается во время инициализации, но когда __getitem__ вызывается; Единственное, что отличает это сообщение исключение, которое не имеет никакого уведомления о __index__ Dunder (который тогда, очевидно, не существует):

Python 2.4 (#1, Sep 11 2016, 18:13:11) 
[GCC 5.4.0 20160609] on linux4 
Type "help", "copyright", "credits" or "license" for more information. 
>>> s = slice(0, Ellipsis) 
>>> [1, 2, 3][s] 
Traceback (most recent call last): 
    File "<stdin>", line 1, in ? 
TypeError: slice indices must be integers 
4

Сторонние библиотеки может захотеть реализовать нарезку для своих собственных объектов , и нет оснований для того, чтобы основной язык ограничивал эти сторонние библиотеки только использованием целых или целочисленных объектов (т. е. объектов, тип которых предоставляет метод __index__) в своих срезах. Вот два примечательных примеров пакетов с использованием не целые числа в нарезку: в NumPy, некоторые объекты принимают сложный шаг, например:

>>> import numpy 
>>> numpy.mgrid[0:2:5j] 
array([ 0. , 0.5, 1. , 1.5, 2. ]) 

И в панд, вы можете нарезать Series или Dataframe объект на этикетке. Эта метка может быть строкой или объектом datetime (например).

>>> import pandas 
>>> s = pandas.Series(range(4), index=['a', 'b', 'c', 'd']) 
>>> s['b':'d'] 
b 1 
c 2 
d 3 
dtype: int64 

Таким образом, для основного языка не было бы смысла создавать исключение при построении среза, содержащего нецелые числа; что сломает вышеупомянутые библиотеки. Вместо этого фактическая операция разреза должна создавать исключение, если компоненты среза (старт, стоп, шаг) не соответствуют соответствующему типу.

Смежные вопросы