Argument Precedence (possible bug?)

Terry Reedy tjreedy at
Sun Mar 5 22:22:31 CET 2006

"vbgunz" <vbgunz at> wrote in message 
news:1141562380.331820.42260 at
> Hello all,
> I am just learning Python and have come across something I feel might
> be a bug.

I feel it is more likely that there in a bug in the communication process 
from the manual to you, on an admittedly somewhat confusing and complex 

> Please enlightenment me...

OK.  Here is my attempt at a summary.

The parameters for a function are the local variable names listed in the 
definition header in ()s after the function name.  There may be any number 
of regular parameters and up to two collection parameters.

The arguments for a function call are the objects listed in ()s after the 
function object (usually but not necessarily indicated by name).
Argument objects are the result of evaluating an expression.
An argument is optionally named by prefixing the expression with 'name=', 
with the restriction that all args after a named arg must also be named.

Regular paramenter names (and slots of collection parameters) are bound to 
argument objects by position or name according to the rules given in the 
manual.  At the end of the process, all parameters and arguments must 
exactly one binding.  (For parameters, the binding may be a default given 
in the definition.)  If not,  an exception is raised and the call aborted.

>How in the world do you provide an argument for *arg4?

You obviously mean par4.  See below for how it gets a non-empty value.

> def argPrecedence(par1, par2=0, par3=0, *par4, **par5):

Par1, par2, and par3 are regular parameters.  They can by matched either by 
position or name on a per-call basis.  Mixing position and name matching in 
any one call is strongly discouraged as confusing and error prone.

Par2 and par3 have default arg objects (calculated when the function is 
defined).  That only means that they do not have to match any of the args 
in a particular call.  It does not determine whether the binding to 
explicit args in a particular call will be by position or name.

>    print 'par1 =', par1, ' # positional argument'
>    print 'par2 =', par2, ' # keyword argument'
>    print 'par3 =', par3, ' # keyword argument'

So these comments are wrong except as they happen to be right for a 
particular call.

Par4 and par5 are leftover-argument collection objects bound by default to 
() and {} respectively if there are, respectively, no leftover positional 
or named args.  So the way to get a nonempty tuple bound to par4 is to have 
a leftover positional arg which requires that you give at least 4 (since 
the first three will be bound to the three regular parameters).

>    print 'par4 =', par4, ' # argument converted to tuple'
>    print 'par5 =', par5, ' # argument converted to dictionary'

Wrong.  Leftover args are placed in, not individually converted to, a tuple 
or dictionary.

> PS. I could be far off with this codes purpose; to try and create an
> example that will house all the different possible parameters
> (positional, keyword, * and **) in one single def statement.

Again, regular parameters are both positional and named, and the matching 
on any particular call can be either (subject to the positional, then named 
args restriction).   In any case, what I think you mean above is not 
possible.  As stated previously, the *leftover_pos_arg tuple will be 
nonempty only if all regular params are positionally matched.

Terry Jan Reedy

More information about the Python-list mailing list