Bizarre behavior with mutable default arguments

thebjorn BjornSteinarFjeldPettersen at gmail.com
Sun Dec 30 12:57:49 EST 2007


On Dec 30, 2:45 pm, Istvan Albert <istvan.alb... at gmail.com> wrote:
> On Dec 30, 5:23 am, thebjorn <BjornSteinarFjeldPetter... at gmail.com>
> wrote:
>
> >    def age(dob, today=datetime.date.today()):
> >        ...
>
> > None of my unit tests caught that one :-)
>
> interesting example I can see how it caused some trouble. A quick fix
> would be to write it:
>
> def age(dob, today=datetime.date.today ):
>
> and inside the definition invoke it as today() rather than just today.
> That way it still keeps the original spirit of the definition.
>
> i.

The purpose of the argument was to be able to calculate the age at a
given point in time -- i.e. was the person 18 y/o at the time of the
incident?

Our coding standard now dictates:

   def foo(arg=None):
       if arg is None:
           arg = <default mutable value>

(unless there's a very good reason to do it otherwise :-)

a close runner-up, that we specifically opted not to allow was

   def foo(arg={}):
       arg = arg or {}

even though it looks sexy and it's perhaps a bit more self-documenting
in some IDEs, it was rejected because it prevents "false" overrides of
the default argument.

For purely practical reasons we couldn't consider

   def foo(arg=None):
       arg = <default mutable value> if arg is None else arg

-- bjorn



More information about the Python-list mailing list