Default mutable parameters in functions

Chris Angelico rosuav at gmail.com
Fri Apr 4 18:47:13 EDT 2014


On Sat, Apr 5, 2014 at 1:34 AM, Steven D'Aprano
<steve+comp.lang.python at pearwood.info> wrote:
> But it's not hard to get that effect in Python, mutable or immutable
> doesn't matter:
>
>
> py> def spam(count, food="spam"):
> ...     spam.__defaults__ = (food,)
> ...     return food*count
> ...
> py> spam(5)
> 'spamspamspamspamspam'
> py> spam(3, 'eggs')
> 'eggseggseggs'
> py> spam(5)
> 'eggseggseggseggseggs'
> py> spam(5, 3)
> 15
> py> spam(4)
> 12
>
>
> Is it so unusual for a function to want to store persistent state which
> survives from one call to another but may also vary from time to time?
> Managing situations like that is one of the reasons OOP was invented!

Maybe it'd be clearer if we change the names around.

def signal(sig, handler=None):
    ret = signals[sig]
    if handler:
        signals[sig] = handler
    return ret

This neatly merges the definitions of signal.signal() and
signal.getsignal(); per the docs:

"""
signal.getsignal(signalnum)

Return the current signal handler for the signal signalnum. The
returned value may be a callable Python object, or one of the special
values signal.SIG_IGN, signal.SIG_DFL or None. Here, signal.SIG_IGN
means that the signal was previously ignored, signal.SIG_DFL means
that the default way of handling the signal was previously in use, and
None means that the previous signal handler was not installed from
Python.

signal.signal(signalnum, handler)

Set the handler for signal signalnum to the function handler. handler
can be a callable Python object taking two arguments (see below), or
one of the special values signal.SIG_IGN or signal.SIG_DFL. The
previous signal handler will be returned (see the description of
getsignal() above). (See the Unix man page signal(2).)
"""

(Incidentally, SIG_IGN and SIG_DFL are just integers. Are they targets
for enumification?)

>>> signal(SIGINT, ctrl_c_handler)
--> whatever the default is
>>> signal(SIGINT)
ctrl_c_handler
>>> signal(SIGINT, other_ctrl_c_handler)
ctrl_c_handler
>>> signal(SIGINT)
other_ctrl_c_handler


I think that's a perfectly reasonable API... it just doesn't happen to
be how Python works by default.

ChrisA



More information about the Python-list mailing list