[Tutor] *args consumption
Smith
smiles at worksmail.net
Sun Mar 12 09:58:00 CET 2006
Danny Yoo wrote:
|| Am I missing some other usage where you wouldn't want to unpack the
|| *arg? If not, would the following "behind the scenes" behavior be
|| possible/preferred?
||
|| ###
|| def foo(*arg):
|| pass
|| ###
||
|| automatically does this
||
|| ###
|| def foo(*arg):
|| if len(arg) == 1:
|| arg = arg[0]
|| pass
|| ###
|
|
| Yes: what if we're passing foo() some mixed data? This might not be
| as weird as it might sound: imagine that a cartegian point [x, y] is
| represented either as a point:
|
| [x, y]
|
| or as a single x coordinate number x where the y coordinate is
| assumed to be zero.
|
| x
|
| Our list would then contain a mix of data. For example, a list with
| the points (4, 3) and (5, 0) and (2, 9) could be represented as:
|
| [[4, 3], 5, [2, 9]]
|
[cut]
| But if we pass playConnectTheDots() with a single point, we want the
| function not to automatically unpack the argument as if it were
| something else: it would be a lossy kind of implicit transformation.
|
OK, I think it's becoming clear. I should think of the *arg in the receiving function as containing a list of things that were sent to it (actually, a tuple). I am likely confusing things a bit because I want to be able to receive an x,y coordinate as foo(x,y) rather than something like foo((x,y)).
| If the case of len(points) == 1 is treated as a special case, that
| would make the logic turn into... well, I don't know, it would be
| ambiguous!
|
As I understand it now, reducing it to a single point rather than leaving it as a tuple of length 1 destroys ones ability to iterate over the items that were passed in. e.g. if you call foo(42) and foo has a *args as its only argument, them automatcally changine the received value of (42, ) to 42 would destroy the ability to loop over args as
###
for arg in args:
#do something
###
As many times as I would prefer to have len == 1 arguments unpacked, if *args automatically behaved this way then likely the other half of the user-universe would be packing up things that have length 0 so they could iterate over them ;-)
###
if len(args) == 0:
args = (args, )
###
| From the example above, if we did feed it:
|
| playConnectTheDots([[4, 3]]) ## Draw the point (4, 3)
|
| vs:
|
| playConnectTheDots([4, 3]) ## Draw between (4, 0) and (3, 0)
|
| then imagine what would happen if Python did the kind of automatic
| unwrapping you're thinking of. How would it tell the difference
| between these two different cases?
|
If playConnectTheDots looks like this,
###
def playConnectTheDots(*points):
if len(points) == 1: points = points[0]
for point in points:
x,y = getX(point),getY(point)
print 'plot %s %s' % (x,y)
###
then I imagine it will work exactly as you are describing :-) I think you meant to call the function like this,
###
playConnectTheDots(*[[4, 3]])
playConnectTheDots(*[4, 3])
###
if the function is defined as this:
###
def playConnectTheDots(*points):
for point in points:
x,y = getX(point),getY(point)
print 'plot %s %s' % (x,y)
###
How would you have written the first line(s) of playConnectTheDots? Or did you mean to pass the values like this:
###
playConnectTheDots(4, 3) #plot 4,0 and 3,0
playConnectTheDots([4, 3]) #plot 4,3
###
/c
More information about the Tutor
mailing list