Hi, I've got some questions on the numpy.vectorize function. Currently, i'm doing this kind of work : [ code] def calc_0d(x, y): """ make complexe calculation using two scalars x and y """ [ ... ] return res1, res2, res 3 # vectorize the function calc = vectorize(calc_0d) res1, res_2, res_3 = calc(array_x, array_y) [/code] This works fine. Really impressive. Good work for this ! My problem is that the complexe calculations made in calc_0d use some parameters, which are currently defined at the head of my python file. This is not very nice and I can't define a module containing theses two functions and call them with different parameters. I would like to make this cleaner and pass theses parameter as keyword argument, but this don't seems to be possible with vectorize. Indeed, some of theses parameters are array parameters and only the x and y arguments should be interpreted with the broadcasting rules.... What is the "good way" for doing this ? Regards, -- LB
Try use a closure. On Jan 30, 12:49 am, LB <berthe.l...@gmail.com> wrote:
Hi,
I've got some questions on the numpy.vectorize function. Currently, i'm doing this kind of work :
[ code] def calc_0d(x, y): """ make complexe calculation using two scalars x and y """ [ ... ] return res1, res2, res 3
# vectorize the function calc = vectorize(calc_0d)
res1, res_2, res_3 = calc(array_x, array_y) [/code]
This works fine. Really impressive. Good work for this !
My problem is that the complexe calculations made in calc_0d use some parameters, which are currently defined at the head of my python file. This is not very nice and I can't define a module containing theses two functions and call them with different parameters.
I would like to make this cleaner and pass theses parameter as keyword argument, but this don't seems to be possible with vectorize. Indeed, some of theses parameters are array parameters and only the x and y arguments should be interpreted with the broadcasting rules....
What is the "good way" for doing this ?
Regards,
-- LB _______________________________________________ Numpy-discussion mailing list Numpy-discuss...@scipy.orghttp://projects.scipy.org/mailman/listinfo/numpy-discussion
On Wed, Jan 30, 2008 at 12:49:44AM -0800, LB wrote:
My problem is that the complexe calculations made in calc_0d use some parameters, which are currently defined at the head of my python file. This is not very nice and I can't define a module containing theses two functions and call them with different parameters.
I would like to make this cleaner and pass theses parameter as keyword argument, but this don't seems to be possible with vectorize. Indeed, some of theses parameters are array parameters and only the x and y arguments should be interpreted with the broadcasting rules....
What is the "good way" for doing this ?
I don't know what the "good way" is, but you can always use functional programming style (Oh, no, CaML is getting on me !): def calc_0d_params(param1, param2, param3): def calc_0d(x, y): # Here your code making use of param1, param2, param3) ... return calc_0d(x, y) you call the function like this: calc_0d_params(param1, param2, param3)(x, y) To vectorize it you can do: calc_0d_vect = lambda *params: vectorize(calc_0d_params(*params)) This is untested code, but I hope you get the idea. It all about partial evaluation of arguments. By the way, the parameters can now be keyword arguments. HTH, Gaël
On a side note, given that I've seen quite a few posts about vectorize() over the past several months... I've written hundreds or thousands of functions that are intended to work with numeric/numpy arrays and/or scalars and I've _never_ (not once!) found a need for the vectorize function. Python's duck-typing has almost always allowed things to work without any (or sometimes with only minor) changes to the function. For example: In [12]: def foo(x, y): ....: return 2.0*x + y In [13]: foo(3.0, 5.0) Out[13]: 11.0 In [14]: foo(arange(4), ones(4)+3.0) Out[14]: array([ 4., 6., 8., 10.]) In [15]: foo(arange(4), 3.0) Out[15]: array([ 3., 5., 7., 9.]) That works fine with arrays, scalars, or array/scalar mixes in the calling. I do understand that more complicated functions might require vectorize(), however, I wonder if sometimes it is used when it doesn't need to be? Scott On Wed, Jan 30, 2008 at 10:22:15AM +0100, Gael Varoquaux wrote:
On Wed, Jan 30, 2008 at 12:49:44AM -0800, LB wrote:
My problem is that the complexe calculations made in calc_0d use some parameters, which are currently defined at the head of my python file. This is not very nice and I can't define a module containing theses two functions and call them with different parameters.
I would like to make this cleaner and pass theses parameter as keyword argument, but this don't seems to be possible with vectorize. Indeed, some of theses parameters are array parameters and only the x and y arguments should be interpreted with the broadcasting rules....
What is the "good way" for doing this ?
I don't know what the "good way" is, but you can always use functional programming style (Oh, no, CaML is getting on me !):
def calc_0d_params(param1, param2, param3): def calc_0d(x, y): # Here your code making use of param1, param2, param3) ...
return calc_0d(x, y)
you call the function like this:
calc_0d_params(param1, param2, param3)(x, y)
To vectorize it you can do:
calc_0d_vect = lambda *params: vectorize(calc_0d_params(*params))
This is untested code, but I hope you get the idea. It all about partial evaluation of arguments. By the way, the parameters can now be keyword arguments.
HTH,
Gaël _______________________________________________ Numpy-discussion mailing list Numpy-discussion@scipy.org http://projects.scipy.org/mailman/listinfo/numpy-discussion
-- -- Scott M. Ransom Address: NRAO Phone: (434) 296-0320 520 Edgemont Rd. email: sransom@nrao.edu Charlottesville, VA 22903 USA GPG Fingerprint: 06A9 9553 78BE 16DB 407B FFCA 9BFA B6FF FFD3 2989
On 30/01/2008, Scott Ransom <sransom@nrao.edu> wrote:
That works fine with arrays, scalars, or array/scalar mixes in the calling. I do understand that more complicated functions might require vectorize(), however, I wonder if sometimes it is used when it doesn't need to be?
It certainly is! I would guess that it gets used for one of two reasons: * People don't realize that it's just a for loop and assume it does numpy magic to make things faster. and * People care more about convenience than speed. I am usually (when I use it) in the second camp. I have some function with a bunch of conditionals - patching up the phase of some inverse trig function, say, or dealing with a few special cases, or cleanly raising exceptions - and it matters more to get the thing written quickly than to have it run quickly. So rather than stop and figure out how to use where() or fancy indexing to handle it efficiently, I just slap a vectorize() on a simple python function. I can always accelerate it later. For the same reason, I often drop into list comprehensions for a few lines, converting back to an array at the end. IMHO, one of the primary values of numpy/scipy is that it lets you express vector algorithms conveniently. When this makes it faster, this is a bonus; when it makes it slower (as sometimes happens with very small or very large arrays) it's a pain. But vectorize() lets me use these vector expressions very readily with functions that are written in a simple python style. Nevertheless, I think (going by some of the questions we get here) a lot of people start using numpy without appreciating that the *point* of using it is that you can use vector expressions; they think, "well, I'm using numbers in python, so I should use numpy", and then they don't take advantage of numpy's speedups. So perhaps we should do some more educating, in tutorials and docstrings, about the limitations of vectorize(). Anyone want to start a wiki page "How to get rid of vectorize()"? Anne
On Jan 30, 2008 2:22 AM, Gael Varoquaux <gael.varoquaux@normalesup.org> wrote:
On Wed, Jan 30, 2008 at 12:49:44AM -0800, LB wrote:
My problem is that the complexe calculations made in calc_0d use some parameters, which are currently defined at the head of my python file. This is not very nice and I can't define a module containing theses two functions and call them with different parameters.
I would like to make this cleaner and pass theses parameter as keyword argument, but this don't seems to be possible with vectorize. Indeed, some of theses parameters are array parameters and only the x and y arguments should be interpreted with the broadcasting rules....
What is the "good way" for doing this ?
I don't know what the "good way" is, but you can always use functional programming style (Oh, no, CaML is getting on me !):
def calc_0d_params(param1, param2, param3): def calc_0d(x, y): # Here your code making use of param1, param2, param3) ...
return calc_0d(x, y)
you call the function like this:
calc_0d_params(param1, param2, param3)(x, y)
To vectorize it you can do:
calc_0d_vect = lambda *params: vectorize(calc_0d_params(*params))
This is untested code, but I hope you get the idea. It all about partial evaluation of arguments. By the way, the parameters can now be keyword arguments.
IIRC, the way to do closures in Python is something like In [5]: def factory(x) : ...: def f() : ...: print x ...: f.x = x ...: return f ...: In [6]: f = factory("Hello world.") In [7]: f() Hello world. There is a reason to do it that way, but I don't recall what it is. Nor do I know if the result can be vectorized, I've never used vectorize. Chuck
On Jan 30, 2008 10:10 AM, Charles R Harris <charlesr.harris@gmail.com> wrote: [SNIP]
IIRC, the way to do closures in Python is something like
In [5]: def factory(x) : ...: def f() : ...: print x ...: f.x = x ...: return f ...:
In [6]: f = factory("Hello world.")
In [7]: f() Hello world.
There is a reason to do it that way, but I don't recall what it is.
You don't need the "f.x = x" line. It's possible it has some beneficial side effect that I don't recall, but basic closures work fine without out. Nor do I know if the result can be vectorized, I've never used vectorize.
I expect they could be, but I don't use vectorize either. -- . __ . |-\ . . tim.hochberg@ieee.org
On Jan 30, 2008 10:18 AM, Timothy Hochberg <tim.hochberg@ieee.org> wrote:
On Jan 30, 2008 10:10 AM, Charles R Harris <charlesr.harris@gmail.com> wrote:
[SNIP]
IIRC, the way to do closures in Python is something like
In [5]: def factory(x) : ...: def f() : ...: print x ...: f.x = x ...: return f ...:
In [6]: f = factory("Hello world.")
In [7]: f() Hello world.
There is a reason to do it that way, but I don't recall what it is.
You don't need the "f.x = x" line. It's possible it has some beneficial side effect that I don't recall, but basic closures work fine without out.
You're right. It looks like the context gets stored in f.func_closure. In [14]: f.func_closure[0].cell_contents Out[14]: 'Hello world.' Chuck
On Jan 30, 2008 10:10 AM, Charles R Harris <charlesr.harris@gmail.com> wrote:
On Jan 30, 2008 2:22 AM, Gael Varoquaux <gael.varoquaux@normalesup.org> wrote:
On Wed, Jan 30, 2008 at 12:49:44AM -0800, LB wrote:
My problem is that the complexe calculations made in calc_0d use some parameters, which are currently defined at the head of my python file. This is not very nice and I can't define a module containing theses two functions and call them with different parameters.
I would like to make this cleaner and pass theses parameter as keyword argument, but this don't seems to be possible with vectorize. Indeed, some of theses parameters are array parameters and only the x and y arguments should be interpreted with the broadcasting rules....
What is the "good way" for doing this ?
I don't know what the "good way" is, but you can always use functional programming style (Oh, no, CaML is getting on me !):
def calc_0d_params(param1, param2, param3): def calc_0d(x, y): # Here your code making use of param1, param2, param3) ...
return calc_0d(x, y)
you call the function like this:
calc_0d_params(param1, param2, param3)(x, y)
To vectorize it you can do:
calc_0d_vect = lambda *params: vectorize(calc_0d_params(*params))
This is untested code, but I hope you get the idea. It all about partial evaluation of arguments. By the way, the parameters can now be keyword arguments.
IIRC, the way to do closures in Python is something like
In [5]: def factory(x) : ...: def f() : ...: print x ...: f.x = x ...: return f ...:
Oops, looks like that needs to be: In [5]: def factory(x) : ...: def f() : ...: print f.x ...: f.x = x ...: return f ...: You can also do something simpler: In [51]: def f() : print f.x ....: In [52]: f.x = "Hello World!" In [53]: f() Hello World! Chuck
Thank you Gael, I think this could work for my case. It will be a bit tricky, since calc_0d is already a closure in which I've defined a function : the parameters x and y are to main parameters of an ODE. So calc_0d define a function, integrate it sing scipy.integrate.odeint and returns some characteristics of the solution. Numpy.vectorize allows me to draw very easily map and contours of theses characteristics. So I will have a function, defining a function, defining another one...
participants (7)
-
Anne Archibald -
Charles R Harris -
Gael Varoquaux -
LB -
Scott Ransom -
Timothy Hochberg -
YW