[Python-3000] pre-PEP: Default Argument Expressions

BJörn Lindqvist bjourne at gmail.com
Thu Feb 15 01:36:18 CET 2007

On 2/14/07, Josiah Carlson <jcarlson at uci.edu> wrote:
> Chris Rebert <cvrebert at gmail.com> wrote:
> > Requesting comments on the following pre-PEP. pybench runs both with and
> > without the patch applied would also be appreciated.
> > - Chris R
> One Glyph Lefkowitz posted today [1] in response to dynamic attribute
> access the following, which is surely applicable here.

To be fair, the two ideas are fairly different. Dynamic attribute
access was about adding new syntax which makes the language more
complex. This idea is more about fine-tuning existing syntax; it does
not add to the language, it just makes it different.

> > I also strongly dislike every syntax that has thus far been proposed,
> > but even if I loved them, there is just no motivating use-case.  New
> > syntax is not going to make dynamic attribute access easier to
> > understand, and it *is* going to cause even more version-compatibility
> > headaches.
> >
> > I really, really wish that every feature proposal for Python had to meet
> > some burden of proof, or submit a cost/benefit analysis.  Who is this
> > going to help?  How much is this going to help them?  "Who is this going
> > to hurt" is easy, but should also be included for completeness -
> > everyone who wants to be able to deploy new code on old Pythons.
> >
> > I suspect this would kill 90% of "hey wouldn't this syntax be neat"
> > proposals on day zero, and the ones that survived would be a lot more
> > interesting to talk about.
> Replace "dynamic attribute access" with "default argument expressions".
> With that said, please provide:

> 1a) Proof as to what is to be gained over an explicit if statement or
> conditional expression.

Two less lines of code? It is hard to grep for it, but I bet there are
a few hundred occurrences the following in the standard library:

    def something(x = None):
        if x is None:
            x = [1, 2, 3]       # <- default

If you remember, it was constructs like this that was one of the big
motivations behind the terniary operator. So now you write the above like this:

    def something(x = None):
        x = [1, 2, 3] if x is None else x

If I remember correctly, the discussion about the terniary operator
was sparked by Raymond Hettinger finding a bug in some code that
erroneously used the and-or-terniary-trick.

But also, often the choice is not between "explicit if statement"
and this. It is between having an obscure and hard to find bug and the
new semantic. I have many, MANY times written bugged code like this:

    def something(x = None):
        if not x:
            x = 42      # <- Oh noe!


    def something(x = []):
        x += ["foobar"]     # <- Even worse!

I guess bugs like these could be explained by stupidity, laziness or
some combination of both. :) Or they could, if other programmers
experience them, be a sign of a deficiency in the language.

> or
> 1b) A cost/benefit analysis of the time it would take to "fix" the
> standard library and/or user code with any of the provided new
> syntax/semantics.

I naively think that Python's test suite would discover most of the
problems. If not, fix the test suite. :) This idea is for py3k, so one
would guess that the allowed cost is higher.

> 2) Who is this going to help (and do we care)?

Me, newbies, lazy programmers or programmers with not enough attention
to details. The last group is fairly big, I think.

> 3) How much is this going to help them?

I think alot. Especially newbies. As said in the PEP, Python's current
default argument evaluation is mentioned in three different lists of
Python's deficiencies.

> 4) Who is this going to hurt (in addition to everyone who wants to run
> new code in older Pythons)?

Everyone that is accustomed to the old behavior. Every book author
whose books become deprecated. On the other hand, the more changes to
the language the more books they can write. :)

I agree that the cost probably is "huge," but so is the benefit,
IMHO. If Python was created today, I bet that default arguments would
be reevaluated at each invocation of the callable.

> Using Glyph's requirements, we see that the syntax is just not
> worthwhile, as stated by most people in the original thread.

Maybe, but it certainly would make some code look much nicer. From

    def is_expired(self, now=None):
        if now is None: now = time.time()
        if (self.expires is not None) and (self.expires <= now):
            return True
        return False

With new semantics:

    def is_expired(self, now = time.time()):
        if (self.expires is not None) and (self.expires <= now):
            return True
        return False

mvh Björn

More information about the Python-3000 mailing list