Argument Precedence (possible bug?)
Terry Reedy
tjreedy at udel.edu
Sun Mar 5 16:22:31 EST 2006
"vbgunz" <vbgunz at gmail.com> wrote in message
news:1141562380.331820.42260 at i40g2000cwc.googlegroups.com...
> 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
subject.
> 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