From: Darren D. <dd...@co...> - 2004-11-15 03:36:41
|
>I guess there is no way in Python of emulating >Matlab"s detection of the number of output arguments. I just got a response from c.l.p. Somebody remembered seeing this at ASPN: http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/284742 expecting() is the workhorse, equivalent to Matlab's nargout: import inspect,dis def expecting(): """Return how many values the caller is expecting""" f = inspect.currentframe() f = f.f_back.f_back c = f.f_code i = f.f_lasti bytecode = c.co_code instruction = ord(bytecode[i+3]) if instruction == dis.opmap['UNPACK_SEQUENCE']: howmany = ord(bytecode[i+4]) return howmany elif instruction == dis.opmap['POP_TOP']: return 0 return 1 def cleverfunc(): howmany = expecting() if howmany == 0: print "return value discarded" if howmany == 2: return 1,2 elif howmany == 3: return 1,2,3 return 1 def test(): cleverfunc() x = cleverfunc() print x x,y = cleverfunc() print x,y x,y,z = cleverfunc() print x,y,z test() |
From: John H. <jdh...@ac...> - 2004-11-15 04:30:14
|
>>>>> "Darren" == Darren Dale <dd...@co...> writes: >> I guess there is no way in Python of emulating Matlab"s >> detection of the number of output arguments. Darren> I just got a response from c.l.p. Somebody remembered Darren> seeing this at ASPN: Darren> http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/284742 Darren> expecting() is the workhorse, equivalent to Matlab's Darren> nargout: Darren> import inspect,dis Hi Darren, Wow, I didn't know this was possible in python. Does it work under python2.2? Perhaps you would like to write up nargin and nargout function with some doc strings and send them my way? I could add them to the matlab interface. But we need to make sure they are 2.2 compliant. As an aside, do we need nargout to make "find" work like matlab's? Isn't it enough just to check the shape of the input array and processing it one way for 1D arrays and another way for 2D arrays? Cheers, JDH |
From: Darren D. <dd...@co...> - 2004-11-15 06:27:08
|
Hi John, > >> I guess there is no way in Python of emulating Matlab"s > >> detection of the number of output arguments. > > Darren> I just got a response from c.l.p. Somebody remembered > Darren> seeing this at ASPN: > Darren> http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/284742 > > Darren> expecting() is the workhorse, equivalent to Matlab's > Darren> nargout: > > Darren> import inspect,dis > > Hi Darren, > > Wow, I didn't know this was possible in python. Does it work under > python2.2? The ASPN page says it has been tested on 2.3.3. I dont have a 2.2 installation handy to check it. > > Perhaps you would like to write up nargin and nargout function with > some doc strings and send them my way? I could add them to the matlab > interface. But we need to make sure they are 2.2 compliant. I will give it a shot in my free time, but without getting into it, my next month is pretty full. > > As an aside, do we need nargout to make "find" work like matlab's? > Isn't it enough just to check the shape of the input array and > processing it one way for 1D arrays and another way for 2D arrays? > The problem is that mlab.find() is currently a thin wrapper around a numeric or numarray method, which only works for 1D arrays. ravelling the arrays passed to find would make it easy to continue using the method called by find(), but I had trouble figuring out how to process the 1xM results of that method back into an NxM or MxN array that could be used to index an N-D array. It would be nice to be able to address Numeric and numarray with a single index. Matlab does this. For example, if a=array([[1,2],[3,4]]), a[0] would be 1, a[1] would be 3 (Matlab's convention, again if memory serves.) -- Darren |
From: Chris B. <Chr...@no...> - 2004-11-15 18:28:10
|
Darren Dale wrote: > >I guess there is no way in Python of emulating > >Matlab"s detection of the number of output arguments. > > I just got a response from c.l.p. Somebody remembered seeing this at ASPN: > http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/284742 > > expecting() is the workhorse, equivalent to Matlab's nargout: Very cool. but I'd caution against using it. I'd much rather see matplotlib be pythonesque than an exact duplicate of MATLAB. This is NOT pythonesque! Precisely speaking, python functions ALWAYS return just one object: A tuple. That tuple can contain any number of other objects, and sequence unpacking means it can look like you're returning multiple values, but you're not really. i.e. def test(): return (1,2,3) # same as return 1,2,3 # now call it: a,b,c = test() (a,b,c) = test() x = test(); a,b,c = x x = test(); a = x[0]; b = x[1]; c = x[2] # Are all equivalent if one uses the last two forms, expecting() will break. -Chris -- Christopher Barker, Ph.D. Oceanographer NOAA/OR&R/HAZMAT (206) 526-6959 voice 7600 Sand Point Way NE (206) 526-6329 fax Seattle, WA 98115 (206) 526-6317 main reception Chr...@no... |
From: John H. <jdh...@ac...> - 2004-11-15 18:56:05
|
>>>>> "Chris" == Chris Barker <Chr...@no...> writes: Chris> Darren Dale wrote: >> >I guess there is no way in Python of emulating >Matlab"s >> detection of the number of output arguments. I just got a >> response from c.l.p. Somebody remembered seeing this at ASPN: >> http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/284742 >> expecting() is the workhorse, equivalent to Matlab's nargout: Chris> Very cool. but I'd caution against using it. I'd much Chris> rather see matplotlib be pythonesque than an exact Chris> duplicate of MATLAB. This is NOT pythonesque! I tend to agree with the caution against using it. But it would be useful in some contexts, like converting existing matlab m-files to python/numeric/numarray, the desire for which has occurred in some contexts. Last time the discussion came up, the lack of nargout was raised as a problem for any converter code. Chris> Precisely speaking, python functions ALWAYS return just one Chris> object: A tuple. That tuple can contain any number of other Chris> objects, and sequence unpacking means it can look like Chris> you're returning multiple values, but you're not Chris> really. i.e. What do you mean that python functions always return a tuple? How about functions that return an int, or a string, or whatever? >>> def func(): return 1 >>> type(func()) <type 'int'> Do you mean that python functions that return tuples always return tuples <wink> ? JDH |
From: Chris B. <Chr...@no...> - 2004-11-15 20:45:51
|
John Hunter wrote: > What do you mean that python functions always return a tuple? How > about functions that return an int, or a string, or whatever? > >>>>def func(): return 1 >>>>type(func()) > > <type 'int'> > > Do you mean that python functions that return tuples always return > tuples <wink> ? no, I was a bit wrong. Python functions always return one object, and when it appears that you are returning multiple objects, you are really returning a single tuple with multiple objects in it. Have I got it right this time? -Chris -- Christopher Barker, Ph.D. Oceanographer NOAA/OR&R/HAZMAT (206) 526-6959 voice 7600 Sand Point Way NE (206) 526-6329 fax Seattle, WA 98115 (206) 526-6317 main reception Chr...@no... |
From: John H. <jdh...@ac...> - 2004-11-15 21:17:22
|
>>>>> "Chris" == Chris Barker <Chr...@no...> writes: Chris> no, I was a bit wrong. Python functions always return one Chris> object, and when it appears that you are returning multiple Chris> objects, you are really returning a single tuple with Chris> multiple objects in it. Have I got it right this time? Sounds right to me. Your answer does point to the danger of using nargout in python ret = somefunc() i,j = ret If somefunc is relying on nargout, it will botch it. I think the only sane use for nargout in python is in auto-conversion scripts, and then with appropriate warnings. Thanks said, I would still like to have it, for that reason. JDH |
From: Darren D. <dd...@co...> - 2004-11-16 01:23:18
|
John Hunter wrote: >>>>>>"Chris" == Chris Barker <Chr...@no...> writes: >>>>>> >>>>>> > > > Chris> no, I was a bit wrong. Python functions always return one > Chris> object, and when it appears that you are returning multiple > Chris> objects, you are really returning a single tuple with > Chris> multiple objects in it. Have I got it right this time? > >Sounds right to me. Your answer does point to the danger of using >nargout in python > > ret = somefunc() > i,j = ret > >If somefunc is relying on nargout, it will botch it. > >I think the only sane use for nargout in python is in auto-conversion >scripts, and then with appropriate warnings. > >Thanks said, I would still like to have it, for that reason. > > Matlab also returns one object- the varargout cell array which is similar to Python's list or tuple. You write a function, and pack varargout with nargout results: [a,b]=matlabfun(). |
From: Chris B. <Chr...@no...> - 2004-11-16 16:53:37
|
Darren Dale wrote: > Matlab also returns one object- the varargout cell array which is > similar to Python's list or tuple. You write a function, and pack > varargout with nargout results: [a,b]=matlabfun(). I haven't used Matlab for a while, and not a newer version than 5.*, but IIRC, while the above notation looks, like you are returning a cell array, you could not call that fun with a single return argument. Perhaps that's changed, in which case you shouldn't use nargout in Matlab either! Anyway, my main point was that kludging a nargout implementation in python was not a good idea. I'd much rather see matplotlib be pythonesque than matlabesque. Perhaps my goals are different than others, but I use Python, rather than Matlab, largely because I like the language better. -Chris -- Christopher Barker, Ph.D. Oceanographer NOAA/OR&R/HAZMAT (206) 526-6959 voice 7600 Sand Point Way NE (206) 526-6329 fax Seattle, WA 98115 (206) 526-6317 main reception Chr...@no... |
From: Darren D. <dd...@co...> - 2004-11-17 00:51:25
|
Hi Chris, >> Matlab also returns one object- the varargout cell array which is >> similar to Python's list or tuple. You write a function, and pack >> varargout with nargout results: [a,b]=matlabfun(). > > > > I haven't used Matlab for a while, and not a newer version than 5.*, > but IIRC, while the above notation looks, like you are returning a > cell array, you could not call that fun with a single return argument. > Perhaps that's changed, in which case you shouldn't use nargout in > Matlab either! Maybe my example wasn't clear. There are good reasons for using varargout and nargout in Matlab. If I write a function to fit a peak, I can return the position, height, FWHM and sumResiduals along with some information about how the peakfitting algorithm concluded. If a user calls [p,h,fwhm,sr] = peakfit(x,y), you use nargout to determine that the caller does not want the algorithm report. > > Anyway, my main point was that kludging a nargout implementation in > python was not a good idea. I'd much rather see matplotlib be > pythonesque than matlabesque. Perhaps my goals are different than > others, but I use Python, rather than Matlab, largely because I like > the language better. > I originally looked into Python because everyone who works with it loves it, and it is free. I felt that the switch could be quick and painless because of John and the other MPL developers efforts with the Matlab interface. I would probably have waited to switch until after graduating if I hadnt googled "Python AND Matlab" one fateful day. (Cornell recently sent me a survey asking whether I felt $230 was fair for a 12 month license!). The matlab interface is already matlabesque. I think *args and Matlab's varargin are equivalent. Let me write up some examples using nargout as it is intended to be used, and I'll submit them to the list in a new thread. This one has strayed a bit from the original topic. Darren |
From: Andrew S. <str...@as...> - 2004-11-17 07:52:29
|
On Nov 16, 2004, at 4:51 PM, Darren Dale wrote: > Maybe my example wasn't clear. There are good reasons for using > varargout and nargout in Matlab. If I write a function to fit a peak, > I can return the position, height, FWHM and sumResiduals along with > some information about how the peakfitting algorithm concluded. If a > user calls [p,h,fwhm,sr] = peakfit(x,y), you use nargout to determine > that the caller does not want the algorithm report. Hi Darren, I sometimes return a dict in cases like this: fit = peakfit(x,y) print fit['position'] print fit['height'] print fit['FWHM'] and so on... Sometimes, the results I always want get returned on their own and optionally return all results: p,h = peakfit(x,y) # return just the basic results p,h,fit_extras = peakfit(x,y,full_output=True) # return everything print fit_extras['FHWM'] (I think some scipy functions operate more-or-less like this, too. Perhaps without returning results in a dict, but merely as extra arguments.) I have to agree with the opinions of Chris Barker and John Hunter cautioning against writing new code using an 'nargout-alike'. (When translating Matlab code to Python I can see that it might be useful.) Furthermore, I often find myself grabbing the results of a function call in one variable, stuffing it somewhere, and later, knowing it's a tuple, examining the elements later. This handy trick would be impossible with an nargout-based implementation. To me, nargout, like so much of Matlab, is a brutish hack introduced because that language is not as capable or elegant as Python. (To digress further and probably show the era at which I left Matlab to be around 5.x, it seems to me that early design mistakes resulted in terrible backwards compatibility issues, as well. For example, I remember being driven mad trying to figure out whether parentheses were needed when calling certain functions. I guess for some they are required and for others they aren't. I think it would be very difficult to define the syntax for Matlab as done in the Python (Language) Reference Manual. And let's not get into issues of object oriented programming, types and 'everything is a (double precision) matrix'.) Regardless of whether your sense of aesthetics is different than mine, the kind of low-level shenanigans suggested as a work-around seems, at the very least, brittle and prone to maintenance and portability issues. (Would that even work on IronPython or PyPy?) Anyhow, if you're not scared by bytecode hacks in your initial toe-dipping forays into Python, I invite you to dive in! Cheers! Andrew |
From: <jk...@ik...> - 2004-11-17 13:10:44
|
[Apologies if this message is a duplicate; it seems that Gmane ate my previous attempt at replying, since I sent another message to the list before acking Gmane's autoreply.] Andrew Straw writes: > To me, nargout, like so much of Matlab, is a brutish hack introduced > because that language is not as capable or elegant as Python. Arguably Matlab has the elegant Lisp-like feature lacking in Python of multiple return values. In Lisp you can write (setq x (floor 3.14)) to set the value of x to 3, or (multiple-value-setq (x y) (floor 3.14)) to set the value of x to 3 and the value of y to 0.14. Note how it is left up to the caller of the FLOOR function whether to capture just the first returned value or both of them. This is paralleled by Matlab's x = some_function(a,b,c) [x,y] = some_function(a,b,c) where the caller decides how many values will be returned. I imagine nargout could have arisen as an optimization aid: if a value is not needed, the function can decide to not compute it. A reasonably good Lisp compiler would probably do this optimization automatically, but Matlab is (or was, until some recent version?) an interpreted language with fewer opportunities for optimization. Where Matlab goes terribly wrong (IMHO) is in that it encourages abuse of the nargout mechanism: built-in functions like find change their behavior depending on how many return values are expected. In effect, the name "find" denotes two different functions, dispatched by the value of nargouts. > Regardless of whether your sense of aesthetics is different than mine, > the kind of low-level shenanigans suggested as a work-around seems, at > the very least, brittle and prone to maintenance and portability > issues. (Would that even work on IronPython or PyPy?) I imagine that the Psyco JIT compiler might have some problems with the hack. I would like to amend my suggestion upthread: instead of changing mlab.find, add another function, say find2 unless someone thinks of a better name, that always returns a tuple. The current version of find could be left as it is, or, even better (this might be important for automatic Matlab-to-Python translation), changed to return a single index for any kind of array. This would require a mechanism for addressing array elements by a single index, which probably doesn't exist. For Matlab compatibility, the addressing should use the column-major, i.e., Fortran, order. In fact, I don't see why this wouldn't solve the problem of automatic translation of functions that use nargout. The value of nargout is a static feature of the function call, so the translator should easily be able to dispatch according to the value, or add it as a keyword argument. That is, if the user has a function like function [a,b]=foo(bar) switch nargout, case 1, a=bar; case 2, a=1; b=bar; end the translator could produce the Python function def foo(bar, nargout=0): if nargout==1: return bar; elif nargout==2: return (1,bar); and translate foo(1); a=foo(2); [b,c]=foo(3); to foo(1); a=foo(2,nargout=1); (b,c)=foo(3,nargout=2); I wouldn't do this for find, since (in my experience) the two-return-value form of find is the more common case, and it would not be very nice to always type in the nargout parameter when using matplotlib interactively. > it seems to me that early design mistakes resulted in terrible > backwards compatibility issues, as well. For example, I remember > being driven mad trying to figure out whether parentheses were > needed when calling certain functions. I guess for some they are > required and for others they aren't. I wonder if this is the same problem that I had for a long time: I finally realized that Matlab either does both auto-parenthesizing and auto-quoting, or neither of them, so print -depsc2 fname is equivalent to print('-depsc2', 'fname') so if you want to create one of the parameters dynamically, you cannot use the first form but will have to write something like print('-depsc2', sprintf('picture-%d', num)) (Then there is the confusion of {} vs () indexing, and cell strings that are almost like real strings but sometimes need a {:} after them, except that if you get them from a function, since the parser gets confused if you type fun(param){:} so you need a temp variable, and cell arrays of structs that sometimes act like structs of cell arrays... Automatic translation of Matlab code will certainly have some interesting challenges.) -- Jouni K Seppänen |