简体   繁体   中英

What is the best way to pass an np.array into a function in Python?

I have a function like this (which I cannot change):

def myFunc(x, y):
    nx = int(x)
    ny = int(y)
    Freq = 0.4

    e0 = 1 * gen.noise2d(Freq * nx, Freq * ny)
    return e0 + 500

Right now, I am trying to use an np.ndarray for other parts of my code, and pass in the x and y values in my loop one at a time:

# passing in a particles which is an array like this:
#     [[2,4], [5, 9], [2, 5]]
# this array would have more than 5000 pairs of x, y coordinates

def mapFunc(particles):
    N = len(particles)
    mask = []
    distance = []

    for i in range(N):
        x = particles[i][0]
        y = particles[i][1]
        ground_dist = mapFunc(x, y)
 
        # add in the distances to the ground
        distance.append(ground_dist)

        # add True if the ground is less than 50 feet away
        mask.append(ground_dist < 50)

    return distance, mask

Is there a better/faster/more efficient way to get the values from my np.ndarray ? Can I somehow pass in the whole arrary into myFunc ? The problem is int(x) and int(y) , not sure how to work with that in Python in regards to an array.

Edit 1 - There was a mistake in the return of myFunc, it was supposed to be using e0 to add 500

Edit 2 - the gen.noise2d is from https://github.com/lmas/opensimplex to "Generate 2D OpenSimplex noise from X,Y coordinates."

You can fully vectorize your code if the following two conditions are met:

  1. gen.noise2d is vectorizable (possibly using the technique shown below), or ignorable
  2. myFunc is a python function, as opposed to one written in C

You can monkeypatch the name int it myFunc 's global namespace to refer to np.around or np.trunc . The latter is closer to what int currently does in the code:

myFunc.__globals__['int'] = np.trunc

You may need to either modify the dependencies of myFunc.__globals__['gen']['noise2d'] , or swap it out entirely. Alternatively, you may want to ignore the noise2d function entirely since its result does not appear to be used in the first place.

Now you can rewrite your code as follows:

def mapFunc(particles):
    particles = np.asarray(particles)
    distance = myFunc(*particles.T)
    mask = distance < 50
    return distance, mask

The line myFunc.__globals__['int'] = np.trunc will modify the __dict__ of the module that myFunc is defined in. This may be a bad thing if you want to use the real int elsewhere in that module. Since the __globals__ attribute is read-only, you can create a copy of the function object with the original code and a different globals. This is likely overkill, so I will link you to the following post: How to create a copy of a python function .

Perhaps a simpler solution is just to bind a different object to the name myFunc , and assign it to the appropriate module?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM