[EMAIL PROTECTED] wrote: > On Apr 2, 3:57 pm, Mel <[EMAIL PROTECTED]> wrote: >> [EMAIL PROTECTED] wrote: >> >> I'd just like to test my >> >>> understanding of this. Suppose I create the following generator >>> object: >>> g = getNextScalar(1, 2, (3, 4), 5) >>> when the iterator reaches the tuple argument (3, 4) then, according to >>> Steve and George, the * in *arg causes this tuple to be expanded into >>> positional arguments, and it makes sense to do it this way. But what >>> happens when getNextScalar(arg) is used instead? >> Try it: >> >> Python 2.5.1 (r251:54863, Mar 7 2008, 04:10:12) >> [GCC 4.1.3 20070929 (prerelease) (Ubuntu 4.1.2-16ubuntu2)] on linux2 >> Type "help", "copyright", "credits" or "license" for more information. >> >>> def a (arg): >> ... print arg >> ... >> >>> def astar (*arg): >> ... print arg >> ... >> >>> a(3,4) >> Traceback (most recent call last): >> File "<stdin>", line 1, in <module> >> TypeError: a() takes exactly 1 argument (2 given) >> >>> astar(3,4) >> (3, 4) >> >>> a((3,4)) >> (3, 4) >> >>> astar((3,4)) >> ((3, 4),) >> >>> >> >> Mel. > > Well, I understand that (unless I missed the point you're trying to > make). But with respect to the example I quoted: > > def getNextScalar(*args): > for arg in args: > if(isinstance(arg, tuple)): > for f in getNextScalar(arg): # should use *arg > yield f > else: > yield arg > where the function is declared as def getNextScalar(*arg), but is > called using getNextScalar(arg), with arg being a tuple: here the > generator is being passed a single argument, so there's no TypeError > as in your example. However, it fails - as I understand it - because > the function keeps passing the same tuple (being unable to access the > elements inside it) and goes into an infinite loop: >>>> # works for this example, but not very useful: >>>> g = getNextScalar(1, 2, 3, 4) >>>> for i in g: > print i > > > 1 > 2 > 3 > 4 > > # third argument is a tuple: >>>> g = getNextScalar(1, 2, (3, 4)) >>>> for i in g: > print i > > > 1 > 2 > > Traceback (most recent call last): > File "<pyshell#108>", line 1, in <module> > for i in g: > File "<pyshell#94>", line 4, in getNextScalar > for f in getNextScalar(arg): > File "<pyshell#94>", line 4, in getNextScalar > for f in getNextScalar(arg): > File "<pyshell#94>", line 4, in getNextScalar > for f in getNextScalar(arg): > ...
Yeah. I feel as though I haven't put the idea clearly. When a function is defined as `def astar (a*)`, then the parameters that it's called with, however many they are, are packed up into one tuple. Illustrated by those print statements. On the calling side, `a (*(3,4))` will unpack the (3,4) tuple and treat the contents as ordinary positional parameters of a. The call `a(*(3,4))` and the call `a(3,4)` are completely equivalent as far as the function a can see. This explanation is going nowhere fast. Anyway, if you define getNextScalar to pack its positional arguments into a tuple that you can iterate over, THEN if you want to feed it a tuple of values to iterate over you have to star-unpack the tuple when you call. The buggy behaviour is continually calling getNextScalar with a single positional parameter (3,4), packing that single parameter into a 1-tuple ((3,4),) , iterating over the 1-tuple to extract (3,4) and calling getNextScalar again -- ad dump. Mel. -- http://mail.python.org/mailman/listinfo/python-list