Mutable default arguments - another approach

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 -- 闇に隠れた黒い力 弱い心を操る

On 1/30/07, Piotr Duda <duda.piotr@gmail.com> wrote:
AFAIK there's no reliable way of deciding whether an arbitrary object is mutable or not, so the rest of the post is irrelevant. Besides, mutable default arguments is just a specific use case; the general problem discussed here is call-time vs definition-time semantics for arbitrary default argument expressions (function calls, attribute lookups, etc.). George

2007/1/30, George Sakkis <george.sakkis@gmail.com>:
AFAIK there's no reliable way of deciding whether an arbitrary object has any feature (except it's type at c level), in worst case you can treat all object as mutable, but that itself doesn't make rest of my post irrelevant (have you even read it?). Read my previous post again, and give me examples of what you cannot do regarding default arguments. -- 闇に隠れた黒い力 弱い心を操る

Piotr Duda wrote:
Read my previous post again, and give me examples of what you cannot do regarding default arguments.
First, I'd like to register my dislike for implicitly determining when a default argument will be copied on every call. Second, as per your request: def foo(bar=None): if bar is None: bar = function_call() #code def foo(bar=None): if bar is None: bar = something.method_call() #code #These were just a few. There are others. These cannot be rewritten using simple copying decorators. Various decorators have been presented that account for some of these (and other) situations. However, IMHO they're not too elegant/clean. Thus, a slightly more sophisticated solution is required. - Chris Rebert

2007/1/31, Chris Rebert <cvrebert@gmail.com>:
In my solution you can do both. Assuming there are all classes/methods defined in my first post, use: @DefaultArgWrapper def calldefarg(callable): #this function should be defined in stdlib while 1: yield callable() first example def foo(bar = calldefarg(function_call)): #code here i assume that function_call is available at definition call, if it isn't then use this def foo(bar = calldefarg(lambda: function_call())): #code and the second example def foo(bar = calldefarg(something.method_call)): #code or if something isn't available at definition time def foo(bar = calldefarg(lambda: something.method_call())): #code there's one restriction, that 'something' cannot depend on other function argument(s).
Are you referring here to my solution? -- 闇に隠れた黒い力 弱い心を操る

George Sakkis wrote:
Maybe Python interpreter could be better at deciding if the programmer which wrote the code is novice or experienced. For example, from __present__ import _I_AM_PYTHON_EXPERT at the beginning of each module will do ;-) Or, alternatively, Python interpreter will read user's directory for some obscure configuration file where programmer will put True's into originally: I_KNOW_WHAT_MUTABLE_MEANS = False I_AM_AWARE_OF_MUTABLE_DEFAULT_ARGUMENT = False ... (And of course, there will be secret I_AM_GUIDO_VAN_ROSSUM = True which will override all the previous settings.) AFAIK, no language has this feature yet (not sure about Perl). Regards, Roman

On 1/30/07, Roman Susi <rnd@onego.ru> wrote:
That would be a good start, but certainly not the end; how about programmers who *read* other people's code ? Their experience level may well be quite different, and the code should be understandable by these poor souls too. The python source files would have to be able to sense when they're being read or printed, determine the experience level of the reader and transform themselves to accomodate his level. Anyone wanna write the PEP for Python-7000 ? ;-) George

Nah, this is all old school. If this pep is gonna succeed it needs some buzzwords like Web 2.0: The interpreter should check with google what kinds of programming-related search terms the programmer has used and for how long. Using google desktop search, it can also include the kind of documents the programmer has and when he's read them. With GvR working where he is, I don't think implementing this is going to be a big problem. ;-) On Tue, 30 Jan 2007 23:11:18 +0100, George Sakkis <gsakkis@rutgers.edu> wrote:

On 1/30/07, Piotr Duda <duda.piotr@gmail.com> wrote:
AFAIK there's no reliable way of deciding whether an arbitrary object is mutable or not, so the rest of the post is irrelevant. Besides, mutable default arguments is just a specific use case; the general problem discussed here is call-time vs definition-time semantics for arbitrary default argument expressions (function calls, attribute lookups, etc.). George

2007/1/30, George Sakkis <george.sakkis@gmail.com>:
AFAIK there's no reliable way of deciding whether an arbitrary object has any feature (except it's type at c level), in worst case you can treat all object as mutable, but that itself doesn't make rest of my post irrelevant (have you even read it?). Read my previous post again, and give me examples of what you cannot do regarding default arguments. -- 闇に隠れた黒い力 弱い心を操る

Piotr Duda wrote:
Read my previous post again, and give me examples of what you cannot do regarding default arguments.
First, I'd like to register my dislike for implicitly determining when a default argument will be copied on every call. Second, as per your request: def foo(bar=None): if bar is None: bar = function_call() #code def foo(bar=None): if bar is None: bar = something.method_call() #code #These were just a few. There are others. These cannot be rewritten using simple copying decorators. Various decorators have been presented that account for some of these (and other) situations. However, IMHO they're not too elegant/clean. Thus, a slightly more sophisticated solution is required. - Chris Rebert

2007/1/31, Chris Rebert <cvrebert@gmail.com>:
In my solution you can do both. Assuming there are all classes/methods defined in my first post, use: @DefaultArgWrapper def calldefarg(callable): #this function should be defined in stdlib while 1: yield callable() first example def foo(bar = calldefarg(function_call)): #code here i assume that function_call is available at definition call, if it isn't then use this def foo(bar = calldefarg(lambda: function_call())): #code and the second example def foo(bar = calldefarg(something.method_call)): #code or if something isn't available at definition time def foo(bar = calldefarg(lambda: something.method_call())): #code there's one restriction, that 'something' cannot depend on other function argument(s).
Are you referring here to my solution? -- 闇に隠れた黒い力 弱い心を操る

George Sakkis wrote:
Maybe Python interpreter could be better at deciding if the programmer which wrote the code is novice or experienced. For example, from __present__ import _I_AM_PYTHON_EXPERT at the beginning of each module will do ;-) Or, alternatively, Python interpreter will read user's directory for some obscure configuration file where programmer will put True's into originally: I_KNOW_WHAT_MUTABLE_MEANS = False I_AM_AWARE_OF_MUTABLE_DEFAULT_ARGUMENT = False ... (And of course, there will be secret I_AM_GUIDO_VAN_ROSSUM = True which will override all the previous settings.) AFAIK, no language has this feature yet (not sure about Perl). Regards, Roman

On 1/30/07, Roman Susi <rnd@onego.ru> wrote:
That would be a good start, but certainly not the end; how about programmers who *read* other people's code ? Their experience level may well be quite different, and the code should be understandable by these poor souls too. The python source files would have to be able to sense when they're being read or printed, determine the experience level of the reader and transform themselves to accomodate his level. Anyone wanna write the PEP for Python-7000 ? ;-) George

Nah, this is all old school. If this pep is gonna succeed it needs some buzzwords like Web 2.0: The interpreter should check with google what kinds of programming-related search terms the programmer has used and for how long. Using google desktop search, it can also include the kind of documents the programmer has and when he's read them. With GvR working where he is, I don't think implementing this is going to be a big problem. ;-) On Tue, 30 Jan 2007 23:11:18 +0100, George Sakkis <gsakkis@rutgers.edu> wrote:
participants (6)
-
Chris Rebert
-
George Sakkis
-
George Sakkis
-
Jan Kanis
-
Piotr Duda
-
Roman Susi