tags:

views:

65

answers:

3

Have a method with the following signature:

def foo(self, bar, *uks):
    return other_method(..., uks)

Normally this is called as:

instance.foo(1234, a, b, c, d)

However in some cases I need to do something like this:

p = [a, b, c, d]
instance.foo(1234, p)

At the receiving end this does not work, because other_method sees *args being made up of a single list object instead of simply a [a, b, c, d] list construct. If I type the method as:

def foo(self, bar, uks = []):
    return other_method(..., uks)

It works, but then I'm forced to do this every time:

instance.foo(1234, [a, b, c, d])

It's not a huge deal I guess, but I just want to know if I'm missing some more pythonic way of doing this?

Thanks!

+3  A: 

Python supports unpacking of argument lists to handle exactly this situation. The two following calls are equivalent:

Regular call:

instance.foo(1234, a, b, c, d)

Argument list expansion:

p = [a, b, c, d]
instance.foo(1234, *p)
Pär Wieslander
Yes, my bad. Missing the `*p` convention in the calling code :) Thanks!
kprobst
+2  A: 
p = [a, b, c, d]
instance.foo(1234, *p)

The *p form is the crucial part here -- it means "expand sequence p into separate positional arguments".

Alex Martelli
That doesn't work though (which is my point), `other_method` sees a tuple whose first item is a list: `print repr(p)` == `([a, b, c, d],)`
kprobst
Are you using the `instance.foo(1234, *p)` calling form along with the `def foo(self, bar, uks = []):` method signature or with `def foo(self, bar, *uks)`?
Corey Porter
Alex - yes, you're right. I didn't realize you were saying that the `*` is used in the _calling code_, all the while I was thinking about the method being called. Thank you!
kprobst
+1  A: 

I think the answers you have here are correct. Here's a fully fleshed out example:

class MyObject(object):
    def foo(self, bar, *uks):
        return self.other_method(1, uks)

    def other_method(self, x, uks):
        print "uks is %r" % (uks,)

# sample data...
a, b, c, d = 'a', 'b', 'c', 'd'

instance = MyObject()

print "Called as separate arguments:"
instance.foo(1234, a, b, c, d)

print "Called as a list:"
p = [a, b, c, d]
instance.foo(1234, *p)

When run, this prints:

Called as separate arguments:
uks is ('a', 'b', 'c', 'd')
Called as a list:
uks is ('a', 'b', 'c', 'd')

You said on Alex's answer that you got ([a, b, c, d],), but I don't see how.

Ned Batchelder
Oh, I see what I was doing wrong -- not prefixing the `p` argument with the `*` modifier, which is why the receiving method was seeing a tuple with a list inside! Thank you for taking the time to reply :)
kprobst