[Tutor] dynamic argument lists

Lie Ryan lie.1296 at gmail.com
Sat Aug 30 19:39:45 CEST 2008


On Sat, 2008-08-30 at 12:00 +0200, tutor-request at python.org wrote:
> 
> Message: 2
> Date: Sat, 30 Aug 2008 10:09:36 +0100
> From: eShopping <etrade.griffiths at dsl.pipex.com>
> Subject: Re: [Tutor] dynamic argument lists
> To: tutor at python.org
> Message-ID: <72l93j$28l2h8 at smtp.pipex.tiscali.co.uk>
> Content-Type: text/plain; charset=us-ascii; format=flowed;
>         x-avg-checked=avg-ok-571D6DEA
> 
> Bob, Kent
> 
> thanks for the suggestions.  Bob made the comment "If there is no 
> compelling requirement that myfunc's argument be in the form **kwargs 
> ...", but I'm afraid I don't understand the difference between
> 
> myfunc (**kwargs)
> 
> and
> 
> myfunc (kwargs)
> 
> Would someone mind explaining this?  I never managed to find a 
> satisfactory explanation for what "**" means!

First you have to understand what ** in a function definition means:
def func(positionalArg, *excessPositionalArg, **excessNamedArg):
    ...

positionalArg is the regular arguments you use, it is accessible by
placing arguments at their respective position and the name it is
assigned to, e.g.

def func1(arg1, arg2, arg3):
    print arg1, arg2, arg3
func1(1, 2, 3)
# 1 2 3

func1(1, 2, 3, 4)
# Wrong number of argument Error

func1(1, arg3 = 2, arg2 = 3)
# 1 3 2

excessPositionalArg is a list of positional arguments that doesn't fit
in the regular positional argument, e.g.

def func2(arg1, arg2, *epa):
    for arg in epa:
        print arg,
func2(1, 2, 3, 4, 5, 6, 7)
# 3 4 5 6 7

last, is excessNamedArg. As we have learned, there are two ways to
access an argument, by its position and by its names,
excessNamedArgument is a dictionary containing the named arguments that
aren't explicitly specified in the function definition, e.g.

def func3(arg1, arg2, *args, **kargs):
    print arg1, arg2,
    for arg in args:
        print '[1 -- %s]' % arg,
    for key, value in kargs:
        print '[2 -- %s: %s]' % (key, value)

func3(1, 2, otherargs = 10):
# 1 2 [2 -- otherargs: 10]

func3(1, arg2 = 2, otherargs1 = 10, otherargs2 = 20)
# 1 2 [2 -- otherargs1: 10]
# [2 -- otherargs2: 20]

Now, to the question, then what is this:
d = {'a':10, 'b':20, arg2: 30}
func3(1, **d)
# 1 30 [2 -- a: 10]
# [2 -- b: 20]

compare:
func3(1, 2, d)
# 1 2 [1 -- {'a':10, 'b':20, arg2: 30}]

If you called it like func3(1, 2, **d), and d is a dictionary, then d
would be expanded and its key/value pair be considered as named
arguments to the function. OTOH, func3(1, 2, d) would pass the whole
dictionary to func3. Since in this case, we have declared a container
for excessPositionalArgument, d is treated as excessPositionalArgument,
if we haven't done that, an bad number of argument error would occur
because there is no more positional argument left.





More information about the Tutor mailing list