"François Pinard" wrote: > > I started recently to study the R system and language, and saw many good > ideas in there about argument passing. Translated in Python terms, it > would mean that `*varargs' and `**keywords' are not necessary last, > that named keywords may be intermixed with positional keywords, that
This would be neat indeed. Occasionally I come across situations where I wished to be able to specify default arguments after positional, as for example in "def accumulate(*items, default=0)". The current possible workarounds are: - pass an iterable instead of positional arguments: "def accumulate(items, default=0)". This is not always elegant, especially if the function is called with few independently derived items (as opposed, for example, to items derived by a list/generator comprehension, which is already an iterable). - pass named keywords instead of default: "def accumulate(*items, **kwds)". I tend to think of **kwds as a nice feature for functions with almost open-ended functionality, that intend to be extended in the future with more customization options. In more typical cases though of a function with one or two defaults, using **kwds obscures the function's signature without a visible benefit. Also, I'm not sure of the efficiency penalty imposed by constructing and passing a dict of length 1 or 2 instead of default arguments. - Put the default(s) before the positional arguments: "def accumulate(default=0, *items)". This practically negates the purpose of using defaults in the first place since the first passed argument is bounded to default. Allowing non-default arguments after *varargs doesn't make sense, but it does for default arguments. The parameter binding rule would just need to be augmented so that default parameter arguments after *varargs would be bounded to their default value unless specified explicitly in the call as named arguments: accumulate(1,2) == accumulate(1,2 default=0) and accumulate([1],[2],default=[]) == accumulate([1],default=[], [2]) == accumulate(default=[], [1], [2]) > keywords may be abbreviated, and much more hairy, Hmm.. -1 on this. It may save a few keystrokes, but it's not good for readability and maintenability. > that the default > values for keywords are not pre-evaluated at `def' time, and that Definitely a +1 on this. I've always seen pre-evaluation as a wart, especially with respect to mutable default values. If some sort of state needs to be preserved between calls, the right way is to encapsulate it in class, not in a default value. > the computation of actual expressions given as arguments is lazily > postponed until their first use within the function. Is this like an implicit lambda before each argument ? If so, why does it have to be restricted to function arguments ? It seems to me that argument passing and lazy evaluation are orthogonal dimensions. Let's keep the "should python become lazy ?" question for a future thread :-) Concerning default argument expressions, a neat feature would be to allow an expression to refer to other arguments, as in "def foo(a,b,s=a+b)" instead of the current workaround which goes like: def foo(a,b,s=None): if s is None: s = a+b Or for a more exotic use: def prologLikeSum(a=s-b, b=s-a, s=a+b): return a,b,s prologLikeSum(1,2) == prologLikeSum(1,s=3) == prologLikeSum(b=2,s=3) == (1,2,3) This seems pretty hard to change though. For one thing, it would require new syntax to denote which names in the expression refer to other arguments instead of the enclosing scope. Also the binding of arguments to values would no more be considered "parallel"; the order of the bindings would be significant, and even worse, it would have to be computed for each call, as the prologLikeSum example shows. Probably-I'm-just-rambling-ly yrs George -- http://mail.python.org/mailman/listinfo/python-list