static variables?

Terry Reedy tjreedy at udel.edu
Wed Nov 20 12:49:56 EST 2002


"Erik Max Francis" <max at alcyone.com> wrote in message
news:3DDB3373.2578CEC0 at alcyone.com...
> Oh, of course; there's really no question why this is the case in
the
> current implementation.

The current implementation follows a very simple rule.  If you want an
expression evaluated when the function is created, you make it a
default argument.  If you want it evaluated upon each call to the
function after it is created, you put it in the body of the function.
There are good reasons for such simple rules.

>  My point is that there is no real a priori
> reason why mutable default arguments couldn't do the equivalent of
>
> def f(x=None):
>     if x is None:
>         x = SomethingMutable
>     ...

If I understand this, you are proposing that if a default is
'mutable', then extra magic be added to re-initialized (somehow) on
every call.  This is, of course, possible -- once you rigorously
define 'mutable' (see 3,4. below) for this context and add a boolean
ismutabledefault() function that works for all possible default
objects -- and define what  'SomethingMutable' is at call time (see 2.
below).  But I think there are arguments against a more complex rule
that some defaults are evaluated upon definition and some upon call.
(Or are you proposing that all defaults be re-evaluated?  If so, then
why have defaults?)

> [For those about to mention the "But what if you really want x to be
> None?" objection, one can simply use a private sentinel object.]

Ugh.  None *is* a (public, global) sentinel object.  Making it do some
automagical special-case switcheroo behind the scenes in one
particular context would complexify the language.  Making people do
something more complex to get an obvious simple result strikes me as a
wrong direction to go.

Other questions/objections:

1. What if one really wants x to be initialized just once - so that
changes *are* carried over from call to call.

2. Suppose the default is, for instance, [a] instead of [], where a is
a global variable.  Will this get the magic treatment?  If so, will
call-time SomethingMutable be the result of evaluating '[a]' at that
time or a copy of a secret, user-inaccessible, stashed-away object
consisting of '[a]' evaluated at definition-time?  If a copy, how
deep?  There is no difference for [] and {}, but there is for most
everything else.  Either choice will be confusing for people who
expect the other, and annoying to people who want the other.

3. Suppose the default is, for instance, ([],).  Considered
superficially (ie, looking only at its outer wrapper, its 'skin'), it
is not mutable  But looking at it as a composite, a layered whole, it
is.  A user who expects [] to be freshed at every call is likely to
expect the same of ([],).  Do you propose to make it so?

4. Do objects currently have a 'mutable' flag?  If you, what do you do
with user-added extension types?

5. Once you start down the road of giving the illusion or actuality of
runtime execution, I suspect that some people will start to expect the
same of all default expressions.

> I don't see a real compelling reason why, if you were to design a
language
> from scratch, you _wouldn't_ want this behavior

As indicated above, 'this behavior' needs more specification.  And
there are reasons to want the current behavior where there is a
difference.

> -- given the unending amount of confusion this feature causes.

Some versions of 'this behavior' could be even more confusing.

> It's pretty obvious why it was done in the implementation --
> because it's the easiest obvious implementation

There is a lot to be said for easy, obvious, and therefore
maintainable-as-bug-free implementations.  Given a facility for
default binding (which could be omitted, of course), there are two
choices of when to create the object bound to a particular parameter:
upon definition and upon call.  Given the latter, there are two
subchoices: copy (to some depth) a hidden master object created at
definition time or re-execute the default expression code.  For a set
of params there two types of choice sets: all the same (choice 1 (the
current behavior), choice 2a (how deep?), or choice 2b) or a mixture
(with probable problems and confusions).

Terry J. Reedy





More information about the Python-list mailing list