[Python-Dev] q about default args

Stepan Koltsov yozh@mx1.ru
Wed, 21 Aug 2002 22:24:51 +0400


Hi, Guido, other Python developers and other subscribers.


First of all, if this question was discussed here or somewhere
else 8086 times, please direct me to discussion archives.
I couldn't guess the keywords to search for in the python-dev archives
as I haven't found the search page where to enter these keywords :-)


The question is: To be or^H^H^H^H^H^H^H^H^H Why not evaluate default
parameters of a function at THE function call, not at function def
(as is done currenly)? For example, C++ (a nice language, isn't it? ;-)
) evaluates default parameters at function call.

Example below illustrates the point in mind:
In Python:

----------
def func(l = []):
    do_something(l)
==========

to make it clearer (though this is not exactly the same):

---

def func(l = list()):
    do_something(l)
   
===

or, in C++:

---

void func(list l = list()) {
    do_something(l)
}

===


Implementation details:

Simple... 
Add a flag to the code object, that means "evaluate default args".
Compile default args to small code objects and store them where values
for default args are stored in current Python (i.e. co_consts). When
a function is called, evaluate the default args (if the above flag
is set) in the context of that function. So, for inst., this code is
now possible:

---

class Tree:
    # this iter walks through a Tree level-wise (i.e. left to right the down).
    def levelIter(self, nodes=[self]):
                            # ^^^^^^ look here
        # the following is not "mission critical"  :-)
        if len(nodes) == 0:
            return
        for node in nodes:
            yield node
        nodes = reduce(operator.add, [n.children() for n in nodes])
        for node in self.levelIter(nodes):
       	    yield node

===

About compatibility: compiled python files stay backward compatible as long as they do not define the mentioned flag.

An alternative way to go (a little example... LOOK ON, PERSONALY, I LIKE IT ALLOT):

---

def f(x=12+[]):
	stmts

===

compiled into something like:

0: LOAD_CONST 1 (12)
1: BUILD_LIST 0
2: BINARY_ADD
3: STORE_FAST 0 (x)
4: # here code of stmts begin

in the case if 'x' was specfied, the code is executed instruction 4
onword This should work perfectly, ideologically correct and I think
even faster then current interpreter implementation.


Motivation (he-he, the most difficult part of this letter):

1. Try to import this module:

---xx.py---

import math
def func(a = map(lambda x: math.sqrt(x)):
	pass
# there is no call to func

===

This code does nothing but define a single function,
but look at the execution time...

2. Currently, default arguments are like static function variables,
defined in the function parameter list! That is wrong.

4. Again: I dislike code like

---

def f(l=None):
    if l is None:
        l = []
    ...

===

5. I asked my friend (also big Python fan): why the current
behaviour is correct?  his answer was: "the curren behaviour is
correct, becausethat is the way it was done in the first place :-)
..." I don't see any advantages of the current style, and lack of
advantages is advantage of new style :-)


I hope, that the current state of things is a result of laziness (or is
it "business"), not sabotage :-) .  and not an ideological decision. It
isn't late to fix Python yet :-) , as when Cpt. J. L. Picard once
again saves the galaxy (this time, not from the evil Borg), it will
be difficult to change self-modificating Python compilers, reconstruct
hardware Python bytecode interpreters and verify tetrabytes of source
code, written in Python  (NOTE: I speek of the not so distant future
:-) )


-- 
mailto: Stepan Koltsov <yozh@mx1.ru>