[Python-ideas] Mutable default arguments - another approach
Piotr Duda
duda.piotr at gmail.com
Tue Jan 30 18:05:40 CET 2007
I think that this problem can be solved by the following change of
default argument behavior:
default arguments are evaluated in definition time (like in current
implementation), but right after being evaluated, result object is
checked if it's mutable (for example by checking of presence __copy__
special method or being instance of built in (sub)class
list/dict/set), if object is mutable, argument is marked by
COPY_DEF_ARG flag.
There are two reasons for this check being done there:
1. performance
2. it can be controlled by "from __future__ import ..." statement in
per-file manner
Then if default argument is needed in function call, first
COPY_DEF_ARG flag is checked if not set, default argument behaves
exactly like in current implementation, if the flag is set, it's
shallow copy is used instead.
Adding following classes/functions to stdlib allow reproduce old
behavior as well as add some new.
class IterateDefaultArg(object):
def __init__(self, iterator):
self.__iterator = iterator
def __copy__(self):
return self.__iterator.next()
class DefaultArgWrapper(object):
def __init__(self, generatorfunc):
self.__generatorfunc = generatorfunc
def __call__(self, *args, **kwargs):
return DefaultArgObject(self.__generatorfunc(*args, **kwargs))
@DefaultArgWrapper
def nocopyarg(obj):
while 1:
yield obj
With this current definition like:
def foo(cache = {}):
...
need to be replaced by:
def foo(cache = nocopyarg({})):
...
If one want to use deep copy instead copy, it might be done like this:
@DefaultArgWrapper
def deepcopyarg(obj):
from copy import deepcopy
while 1:
yield deepcopy(obj)
def foo(x = deepcopyarg(<some expression>)):
...
P.S. sorry for my bad English
--
闇に隠れた黒い力
弱い心を操る
More information about the Python-ideas
mailing list