В чем разница между собственным типом int и numpy.int типы?

#python #numpy

Вопрос:

Не могли бы вы помочь понять, каковы основные различия (если таковые имеются) между собственным типом int и типами numpy.int32 или numpy.int64?

Ответ №1:

Есть несколько основных отличий. Во-первых, целые числа python имеют гибкий размер (по крайней мере, в python 3.x). Это означает, что они могут вырасти, чтобы вместить любое число любого размера (в пределах ограничений памяти, конечно). С другой стороны, целые числа numpy имеют фиксированный размер. Это означает, что существует максимальное значение, которое они могут удерживать. Это определяется количеством байтов в целочисленном ( int32 vs int64 ), при этом большее количество байтов содержит большие числа, а также является ли число подписанным или беззнаковым ( int32 vs uint32 ), причем беззнаковое число может содержать большие числа, но не может содержать отрицательное число.

Итак, вы можете спросить, зачем использовать целые числа фиксированного размера? Причина в том, что современные процессоры имеют встроенные инструменты для выполнения математики с целыми числами фиксированного размера, поэтому вычисления на них выполняются намного, намного, намного быстрее. Фактически, python использует целые числа фиксированного размера за кулисами, когда число достаточно мало, переключаясь на более медленные целые числа гибкого размера, когда число становится слишком большим.

Еще одним преимуществом значений фиксированного размера является то, что они могут быть помещены в соседние блоки памяти одинакового типа одинакового размера. Это формат, который массивы numpy используют для хранения данных. Библиотеки, на которые полагается numpy, способны выполнять чрезвычайно быстрые вычисления с данными в этом формате, на самом деле современные процессоры имеют встроенные функции для ускорения такого рода вычислений. С целыми числами python переменного размера такого рода вычисления невозможны, потому что невозможно сказать, насколько большими должны быть блоки, и нет согласованности в формате данных.

Тем не менее, numpy на самом деле способен создавать массивы целых чисел python. Но вместо массивов, содержащих значения, вместо этого они представляют собой массивы, содержащие ссылки на другие части памяти, содержащие фактические целые числа python. Это не может быть ускорено таким же образом, поэтому, даже если все целые числа python соответствуют фиксированному целочисленному размеру, оно все равно не будет ускорено.

Ничего из этого не относится к Python 2. В Python 2 целые числа Python являются фиксированными целыми числами и, таким образом, могут быть непосредственно переведены в целые числа numpy. Для целых чисел переменной длины в Python 2 был такой long тип. Но это сбивало с толку, и было решено, что эта путаница не стоит повышения производительности, особенно когда люди, которым нужна производительность, все равно будут использовать numpy или что-то в этом роде.

Ответ №2:

Другой способ взглянуть на различия-спросить, какими методами обладают объекты 2-х типов.

В Ipython я могу использовать вкладку завершено для просмотра методов:

 In [1277]: x=123; y=np.int32(123)
 

int методы и атрибуты:

 In [1278]: x.<tab>
x.bit_length   x.denominator  x.imag         x.numerator    x.to_bytes
x.conjugate    x.from_bytes   x.real         
 

int «операторы»

 In [1278]: x.__<tab>
x.__abs__           x.__init__          x.__rlshift__
x.__add__           x.__int__           x.__rmod__
x.__and__           x.__invert__        x.__rmul__
x.__bool__          x.__le__            x.__ror__
...
x.__gt__            x.__reduce_ex__     x.__xor__
x.__hash__          x.__repr__          
x.__index__         x.__rfloordiv__     
 

np.int32 методы и атрибуты (или свойства). Некоторые из них такие же, но намного больше, ndarray в основном все:

 In [1278]: y.<tab>
y.T             y.denominator   y.ndim          y.size
y.all           y.diagonal      y.newbyteorder  y.sort
y.any           y.dtype         y.nonzero       y.squeeze   
...
y.cumsum        y.min           y.setflags      
y.data          y.nbytes        y.shape   
 

y.__ методы очень похожи на int те, что были. Они могут делать ту же математику.

 In [1278]: y.__<tab>
y.__abs__              y.__getitem__          y.__reduce_ex__
y.__add__              y.__gt__               y.__repr__
...
y.__format__           y.__rand__             y.__subclasshook__
y.__ge__               y.__rdivmod__          y.__truediv__
y.__getattribute__     y.__reduce__           y.__xor__
 

y во многом это то же самое, что и массив 0d. Не идентичные, но близкие.

 In [1281]: z=np.array(123,dtype=np.int32)
 

np.int32 это то, что я получаю, когда индексирую массив такого типа:

 In [1300]: A=np.array([0,123,3])

In [1301]: A[1]
Out[1301]: 123

In [1302]: type(A[1])
Out[1302]: numpy.int32
 

Я должен использовать item , чтобы удалить всю numpy обертку.

 In [1303]: type(A[1].item())
Out[1303]: int
 

Как numpy пользователь, an np.int32 -это an int с numpy оболочкой. Или, наоборот, один элемент an ndarray . Обычно я не обращаю внимания на то A[0] , дает ли мне «родной» int или эквивалент numpy. В отличие от некоторых новых пользователей, я редко использую np.int32(123) ; я бы использовал np.array(123) вместо этого.

 A = np.array([1,123,0], np.int32)
 

не содержит 3 np.int32 объектов. Скорее, его буфер данных имеет длину 3*4=12 байт. Это накладные расходы массива, которые интерпретируют его как 3 дюйма в 1d. И view показывает мне один и тот же буфер данных с разными интерпретациями:

 In [1307]: A.view(np.int16)
Out[1307]: array([  1,   0, 123,   0,   0,   0], dtype=int16)

In [1310]: A.view('S4')
Out[1310]: array([b'x01', b'{', b''],   dtype='|S4')
 

Только когда я индексирую один элемент, я получаю np.int32 объект.

Список L=[1, 123, 0] отличается; это список указателей — указателей на int объекты, находящиеся в памяти в другом месте. Аналогично для массива dtype=object.

Ответ №3:

Я думаю, что самая большая разница заключается в том, что типы numpy совместимы с их аналогами на языке C. Во-первых, это означает, что numpy ints может переполниться…

 >>> np.int32(2**32)
0
 

Вот почему вы можете создать массив целых чисел и указать тип данных, np.int32 например. Затем Numpy выделит массив, достаточно большой, чтобы вместить указанное количество 32-разрядных целых чисел, а затем, когда вам понадобятся значения, он преобразует C-целые числа в np.int32 (что очень быстро). Преимущества возможности преобразования туда и обратно из np.int32 C-int и C-int также включают огромную экономию памяти. Объекты Python, как правило, довольно большие:

 >>> sys.getsizeof(1)
24
 

А np.int32 ничуть не меньше:

 >>> sys.getsizeof(np.int32(1))
28
 

но помните, что большую часть времени, когда мы работаем с массивами numpy, мы работаем только с целыми числами C, которые занимают всего 4 байта (вместо 24). Нам нужно работать только с тем np.int32 , когда мы имеем дело со скалярными значениями из массива.

Комментарии:

1. Можете ли вы подтвердить 24 и 28 размер?

2. Я думаю, что 24-это накладные расходы практически любого объекта python. 28 связано с тем, что нам нужно было создать объект python и вставить в него целое число c-я думаю (хотя я могу ошибаться-я не разработчик numpy или что-то в этом роде). Однако, когда вы упаковываете множество c-целых чисел в массив numpy, вам нужен только 1 объект python для всех этих целых чисел.