assignment expression peeve

Terry Reedy tjreedy at udel.edu
Mon Oct 20 22:33:48 EDT 2003


"Carl Banks" <imbosol at aerojockey.invalid> wrote in message
news:TVUkb.6149$Vf7.4143 at nwrdny02.gnilink.net...
> >    foo(bar=23, baz=45)

> I would parse the above as "foo, with bar equal to 23, baz equal to
> 45."  This is going to sound silly, but I'm serious: because there's
> no assignment there,

On the contrary, besides the call, assignment is all there is.  bar
and baz are bound to 23 and 45 either in foo's local namespace (if
they appear in foo's arg list) or in foo's **dic (if they are not in
the arg list and there is a **dic in the arg list) or an error is
raised .

Assignment expressions differ from assignment statements in that they
*also* 'return' the value to the expression's context as the value of
the expression.  They 'tee' the righthand expression result to both
the name binder and the local context.  In function calls like above,
there is no teeing.  The call is *not* the same as foo(23,45) unless
bar and baz happens to be the first two positional params.

  Compare this with
    while (a=next()) != 3:
For the purpose of computing the condition, this is the same as
    while next() != 3:
The assignment is only a side-effect allowing possible later use of
the value assigned, after it is used first to resolve the condition
expression.  The assigment expression might better be written
    while (a=)next() != 3:
to emphasize the double use of next's return value.

In the function call, the assignment for later use is all there is.
There is no teeing for immediate use.

> Incidentally, default arguments in a function definition is a lot
> worse--a lot of people do take them as assignments,

Which they are.

Default object assignments are much like call keyword assigments in
that the expression is evaluated outside of the function's locals
while the binding is done within the function's locals.

> and are surprised  when their code doesn't work as expected.

The confusion results from Python function objects have two types of
'runtime': one definition/construction time and 0 to many
call/execution times.

The assignment works exactly as expected, but is done only once at
construction time instead of once at each of possibly many execution
times.  If a def is run multiple times to generate multiple function
objects, then the defaults are recalculated (in the def's context) for
each function object, but still only once for each.

Terry J. Reedy






More information about the Python-list mailing list