Диапазон Python с np.intc

#python #numpy #integer #range

#python #numpy #целое число #диапазон

Вопрос:

Вчера я задал здесь вопрос о странном поведении python range() . Я случайно использовал range() вместо np.arange() . Но в зависимости от входного int-типа он работает для математических операций или нет. Это было в огромном контексте, поэтому я упростил задачу.

 import numpy as np 

"""
DOES WORK
"""
x1 = np.intc(545)
x2 = np.intc(1048)
x_axis = range(x1, x2) 
test = (x_axis - x1) # should throw exception, but works
type(x_axis[0]) # numpy.int32 / intc

"""
DOESNT WORK
"""
t1 = 545
t2 = 1048
t_axis = range(t1, t2)
test2 = (t_axis - t1) # throws TypeError unsupported operand type(s) for -: 'range' and 'int'
 

Предыстория:
Причина использования intc-datatype заключается в том, что моя программа выполняет некоторые другие задачи, такие как поиск пиков и т. Д., И я использую некоторые списки для создания списка из вычисленных пиков. После некоторых других шагов я использую x1 и x2 из этого списка пиков (который, очевидно, не является обычным списком целых чисел). Итак, вчера я изменил свой код и сгенерировал новый список, а затем произошло исключение. Я предполагаю, что numpy / scipy использует внутренний intc.

Может ли кто-нибудь объяснить такое поведение?

Ответ №1:

Последовательности и скаляры Python ведут себя иначе, чем массивы и скаляры numpy 1d. Давайте рассмотрим несколько основных примеров, чтобы разобраться в этом (или перейдем к нижней части, если спешите):

 # define our test objects
a_range = range(2,6)
a_list = list(a_range)
a_array = np.array(a_list)

# ranges don't add
a_range a_range
# Traceback (most recent call last):
#   File "<stdin>", line 1, in <module>
# TypeError: unsupported operand type(s) for  : 'range' and 'range'

# lists do add but with different semantics ...
a_list a_list
# [2, 3, 4, 5, 2, 3, 4, 5]

# ... from numpy arrays
a_array a_array
# array([ 4,  6,  8, 10])

# what happens if we mix types?

# range and list don't mix:
a_range a_list
# Traceback (most recent call last):
#   File "<stdin>", line 1, in <module>
# TypeError: unsupported operand type(s) for  : 'range' and 'list'

# but as soon as there is a numpy object involved it "wins":
    
a_range a_array
# array([ 4,  6,  8, 10])

a_list a_array 
# array([ 4,  6,  8, 10])

# How about scalars?

py_scalar = 3
np_scalar = np.int64(py_scalar)

# again, in pure python you cannot add something to a range ...
a_range py_scalar
# Traceback (most recent call last):
#   File "<stdin>", line 1, in <module>
# TypeError: unsupported operand type(s) for  : 'range' and 'int'

# or a list
a_list py_scalar
# Traceback (most recent call last):
#   File "<stdin>", line 1, in <module>
# TypeError: can only concatenate list (not "int") to list

# but you can add a Python or numpy scalar to a numpy object
a_array py_scalar
# array([5, 6, 7, 8])

a_array np_scalar
# array([5, 6, 7, 8])

# Now if the scalar is a numpy object, again, it "wins":

a_range np_scalar
# array([5, 6, 7, 8])

a_list np_scalar
# array([5, 6, 7, 8])
 

Итак, подводя итог, последовательности Python и массивы numpy 1d имеют разную семантику, в частности, с двоичными операторами, такими как » » или «-» или «*». Если хотя бы один операнд является объектом numpy (массивом или скаляром), выигрывает numpy: объекты, отличные от numpy, будут преобразованы (плоские последовательности становятся одномерными массивами), и будет применяться семантика numpy.

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

1. Спасибо за ваш подробный ответ! Теперь я знаю немного больше о поведении 😉