2017-06-01 24 views
13

把這個代碼:itertools沒有關於Python 3.6認識numpy的整數作爲有效輸入

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.int32itertools封裝的其他方法拋出類似的錯誤,例如當你使用permutations時,你會得到TypeError: Expected int as r

除了this numpy issue以及其他相關產品之外,我無法在這方面找到太多內容,但是那個在3年前已經關閉,這意味着它已經解決了。

像索引numpy整數data[dw[0]]或布爾比較像dw[0] == 1工作就好了。

我錯過了什麼嗎?這可能是一個Python 3的錯誤?

+0

最簡單的解決方法是使用類型轉換:int(dw [0]),int(dw [1])' – TheDarkKnight

+0

即使它工作,py2.7,使用數組而不是列表會更慢。 – hpaulj

+1

正是那種讓我討厭Python的東西。 –

回答

13

一個numpy.int64顯然不是的int

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

type(a)

numpy.int64 

isinstance(a, int)

一個子類10
False 

numpy的文件

documentation提到了這一點明確

警告

的int_類型不從內置Python 3下的INT繼承, 因爲int類型是不更長的固定寬度整數類型。

解決方案

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

或numpy的切片

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

祝福顯式類型轉換 – TheDarkKnight

+1

那麼爲什麼'itertools.islice'需要'int's,而沒有它們的常規列表切片就沒事了(例如'data [dw [0]]')? –

+3

@Chris_Rands:常規列表切片和索引支持實現'__index__'方法的任何東西。 NumPy整數類型實現該方法。 –

1

如果你想保持islice/slice狀物體,使用np.s_

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

['b', 'c'] 

因爲np.s_是一個numpy的對象,它不介意整數的numpy

+0

定期切片從來不是問題; 'list(it.islice(data,np.s_ [dw [0]]))'仍然失敗 –

+0

重點是跳過創建一個'iterable'對象,並使用具有等價函數的'numpy'對象。其他答案涵蓋了'itertools'失敗的原因。 –

+0

但是,簡單地說'data [dw [0]:dw [1]]'可以工作 –

6

我不確定它是否是Python 3中的錯誤,但看起來行爲在2.7以後發生了變化。正如numpy issue you linked所述,在py27下,numpy.int32numpy.int64看起來是int的一個子類(取決於你使用Python的32位還是64位版本)。在py3下,類型不再相關(numpy有固定寬度的數字類型,python的int是可變寬度)。

implementation of itertools.islice要求其參數是PyLong類型的對象(which is the Python API name for the Python int type)。具體來說,它調用PyLong_AsSize_t,它將Python對象轉換爲C size_t值。此方法似乎要求其參數實際上是一個Python int對象,因爲它調用PyLong_Check。我認爲這種方法大致相當於Python的isinstance(obj, int),它解釋了py2和py3在這裏的行爲差異。

Normal list indexing使用另一個更寬容的方法將參數強制轉換爲正整數值,稱爲PyNumber_AsSsize_t。 這將檢查它的參數是否爲int,如果不是,則返回嘗試調用其參數的方法__index__;正如@MarkDickinson指出的那樣,numpy的數字類型實現了這個方法,所以一切正常。也許這對於itertools.islice來說會更直觀。

+0

鑑於諸如索引或布爾比較這樣的工作很好,不應該認爲這是一個錯誤?顯然,許多更多的基本功能是以一種可行的方式實現的。 – Khris

+1

@Khris我個人傾向於認爲這是'islice'的缺點,是的。讓'islice'消費任何以某種方式「數字」的參數似乎更明智(例如,包括基本類型'np。integer')。 – wildwilhelm

3

這看起來像一個__index__神奇方法的案例(numpy的整數已經實現)。我建議在跟蹤器上提出一個問題,要求將其作爲增強功能 - 即接受任何實施__index__的對象。

相關問題