Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
411 views
in Technique[技术] by (71.8m points)

numpy - Python range with np.intc

Yesterday I asked here a question about a weird behavior of python range(). I accidentally used range() instead of np.arange(). But depending on the input int-type it works for mathematical operations or not. It was in a huge context, so I simplified the problem.

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'

Background: The reason for using intc-datatype is that my program performs some other tasks like peakfinding etc. and I use some list-comprehensions for generating a list out of the calculated peaks. After some other steps, I use x1 and x2 out of this peak-list (which isn't a normal list of ints obviously). So I changed yesterday my code and generated a new list and then the exception occured. My guess is that numpy/scipy uses internally intc.

Can someone explain this behavior?

question from:https://stackoverflow.com/questions/65952109/python-range-with-np-intc

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Python sequences and scalars behave differently from numpy 1d arrays and scalars. Let's run through a few basic examples to get the hang of it (or skip to bottom if in a hurry):

# 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])

So to summarize, Python sequences and numpy 1d arrays have different semantics, in particular, with binary operators like "+" or "-" or "*". If at least one operand is a numpy object (array or scalar) numpy wins: Non numpy objects will be converted (flat sequences become 1d arrays) and numpy semantics will apply.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...