Подтвердить что ты не робот

Itertools не распознает numpy int как действительные входы на Python 3.6

Возьмите этот код:

import itertools as it
import numpy as np
data = ['a','b','c','d']
dw = np.array([1, 3], dtype=np.int64)
print(list(it.islice(data,dw[0],dw[1],1)))

В Python 2.7 он печатает ['b', 'c',], как ожидалось.

В Python 3.6 он генерирует исключение:

ValueError: Stop argument for islice() must be None or an integer: 0 <= x <= sys.maxsize.

То же самое относится к np.int32, а другие методы пакета itertools вызывают подобные ошибки, например. когда вы используете permutations, вы получаете TypeError: Expected int as r.

Я не мог найти многого, кроме этой проблемы с numpy и связанных с ней, но этот был закрыт 3 года назад, подразумевая, что это было решена.

И основные вещи, такие как индексирование с numpy ints data[dw[0]] или логические сравнения, такие как dw[0] == 1, работают очень хорошо.

Я что-то упустил? Может ли это быть ошибкой Python 3?

4b9b3361

Ответ 1

a numpy.int64, по-видимому, не является подклассом int

a, b = dw[0], dw[1]

type(a)

numpy.int64

isinstance(a, int)

False

Документация по номеру

В документации упоминается это явно

Предупреждение

Тип int_ не наследуется от встроенного в Python 3, потому что тип int больше не является целым типом фиксированной ширины.

Решение

print(list(it.islice(data, int(dw[0]) , int(dw[1]), 1)))

или numpy slicing

data[dw[0]:dw[1]:1]

Ответ 2

Я не уверен, что это ошибка в Python 3 или нет, но похоже, что поведение изменилось с 2.7. В качестве проблемы с numpy, которую вы связали, описано в py27, либо numpy.int32, либо numpy.int64 будет являться подклассом int ( в зависимости от того, используете ли вы 32- или 64-битную сборку Python); под py3 типы больше не связаны (numpy имеет числовые типы с фиксированной шириной, python int - переменная ширина).

реализация itertools.islice требует, чтобы его аргументы были объектами типа PyLong (который является именем API Python для типа Python int). В частности, он вызывает PyLong_AsSize_t, который преобразует объект Python в значение C size_t. Этот метод, по-видимому, требует, чтобы его аргумент был фактически объектом Python int, так как он вызывает PyLong_Check. Я думаю, что этот метод в целом эквивалентен Python isinstance(obj, int), что объясняет разницу в поведении между py2 и py3 здесь.

Индексирование нормального списка использует другой более толерантный метод для приведения аргументов в положительные целочисленные значения, называемые PyNumber_AsSsize_t.  Это проверяет, является ли его аргумент int и, если нет, возвращается к попытке вызвать его аргумент __index__ method; как указывает @MarkDickinson, числовые типы numpy реализуют этот метод, поэтому все работает нормально. Возможно, это было бы более интуитивно понятным для itertools.islice.

Ответ 3

Это похоже на случай магического метода __index__ (который уже реализует целые числа numpy). Я предлагаю поднимать проблему на трекер, запрашивая это как усовершенствование, - что islice принимает любой объект, который реализует __index__.

Ответ 4

Если вы хотите сохранить объект islice/slice -like, используйте np.s_:

slice = np.s_[dw[0]: dw[1]: 1]
data[slice]

['b', 'c']

поскольку np.s_ является объектом numpy, он не имеет против целых чисел numpy.