2012-09-17 5 views
6

Próbuję zawinąć głowę wokół numpy implementacji PEP3118. Jak dokładnie działa dostęp do bufora w trybie numpy.numpy.getbuffer i numpy.frombuffer

>>> p = numpy.getbuffer(numpy.arange(10)) 
>>> p 
<read-write buffer for 0x1003e5b10, size -1, offset 0 at 0x1016ab4b0> 
>>> numpy.frombuffer(p) 
array([ 0.00000000e+000, 4.94065646e-324, 9.88131292e-324, 
    1.48219694e-323, 1.97626258e-323, 2.47032823e-323, 
    2.96439388e-323, 3.45845952e-323, 3.95252517e-323, 
    4.44659081e-323]) 

Otrzymuję nieoczekiwane zwroty. Spodziewałbym się tablicy z 10 elementami od 0 do 9. Mogę wejść do tablicy i czytać/pisać.

>>> j = numpy.frombuffer(p) 
>>> j 
array([ 0.00000000e+000, 4.94065646e-324, 9.88131292e-324, 
    1.48219694e-323, 1.97626258e-323, 2.47032823e-323, 
    2.96439388e-323, 3.45845952e-323, 3.95252517e-323, 
    4.44659081e-323]) 
>>> j += 1 
>>> j 
array([ 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.]) 

Wygląda na to, że bufor inicjalizuje wszystkie zera, do których mogę następnie pisać. Funkcją, której oczekuję, jest możliwość zbudowania tablicy (z arange lub asarray) bezpośrednio do bufora z getbuffer. Czy to nie jest możliwe?

Odpowiedz

14

Masz prosty problem z dtype. Bufor utworzyć z

np.getbuffer(np.arange(10)) 

ma dtype=int, ponieważ np.arange wykorzystuje dtype=int domyślnie.

Potem, kiedy próbują odczytać bufor z

np.frombuffer(p) 

jesteś w rzeczywistości przy użyciu domyślnego np.frombufferdtype=float. Zamiast tego należy użyć

np.frombuffer(p, dtype=int) 

et voila, masz

array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) 
8

Dodam kilka uwag na doskonałą istniejącego answer przez Pierre.

Trzeba getbuffer tylko wtedy, gdy trzeba pokroić ndarray: można pobrać obiekt bufora pyton związanego z całej macierzy za pomocą atrybutu

>>> import numpy as np 
>>> a = np.arange(10) 
>>> a.data == np.getbuffer(a) 
True 

Wręcz przeciwnie data, nie trzeba zdać rzeczywisty obiekt buforowy do funkcji frombuffer, każdy obiekt, który eksponuje interfejs buffer jest dobry.

>>> np.frombuffer(a, a.dtype) 
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) 
>>> np.frombuffer(a) 
array([ 0.00000000e+000, 4.94065646e-324, 9.88131292e-324, 
     1.48219694e-323, 1.97626258e-323, 2.47032823e-323, 
     2.96439388e-323, 3.45845952e-323, 3.95252517e-323, 
     4.44659081e-323]) 
>>> import array 
>>> c = array.array('i', range(10)) 
>>> np.frombuffer(c, np.int32) 
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], dtype=int32) 
>>> np.frombuffer(c) 
array([ 2.12199579e-314, 6.36598737e-314, 1.06099790e-313, 
     1.48539705e-313, 1.90979621e-313]) 

Kiedy dekodowanie obiekt bufora, trzeba znać poprawną dtype Jako przykłady wyżej wykazać. Aby być bardziej precyzyjnym, obiekty buforowe nie mają wartości dtype: są po prostu strumieniem danych binarnych. Zamiast tego obiekty ndarray mają dtype, który dyktuje interpretację podstawowych danych binarnych.

Aby odpowiedzieć na pytanie: każdy numpy ndarray odsłania interfejs bufora. Dostęp do bufora lub jego fragmentu można uzyskać za pomocą deskryptora data lub funkcji getbuffer. Możesz utworzyć ndarray z obiektu eksponującego interfejs bufora za pomocą funkcji frombuffer. Ponieważ bufor (w przeciwieństwie do ndarrays) nie ma informacji dtype, należy zawsze wyraźnie określić, w jaki sposób bufor musi zostać zinterpretowany za pomocą argumentu dtype dla frombuffer.

+0

Co za wspaniały dodatek do odpowiedzi Pierre'a.Dodatkowy szczegół jest bardzo doceniany. – Jzl5325