Default parameters

Stian Søiland stain at stud.ntnu.no
Wed Dec 17 01:20:54 EST 2003
* J.R. spake thusly:
> >    def f(d=[]):
> >       d.append(0)
> >       print d
> >    f()
> >    f()
> > Explain results.  When is d bound?

When is this issue going to be resolved? Enough newbie-pythoners have
made this mistake now.

Why not evaluate the parameter lists at calltime instead of definition
time? This should work the same way as lambdas.

>>> f = lambda: []
>>> a=f()
>>> b=f()
>>> a.append(1)
>>> print a, b
[1] []


Maybe this could be defined in a similar way to remind of the
"lazy-evaluation":

def getvalue(cls):
    return "OK"

class SomeClass:
    def blapp(something: getvalue(), other: []):
        print something, other

This way, the lambda forms defined after 'something' and 'other' are
evaluated each time the function is called without supplying those
parameters.

The lambda forms could be evaluated as if within the class-block, and
therefore they might actually use other values defined within that
namespace. However, this might again confuse users, as subclassed
attributes and instance attributes would not be resolved that way.

(Note that default-parameters-lambdas by today does NOT resolve this way:

>>> class Blapp:
...   ting = 15
...   def fix(self, per=lambda: ting):
...     print per()
...
>>> a = Blapp()
>>> a.fix()
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
  File "<stdin>", line 4, in fix
  File "<stdin>", line 3, in <lambda>
  NameError: global name 'ting' is not defined



Finally, things could also be done like this, to avoid confusion to all
those new folks (our main goal):

def blapp(something=getvalue(), other=[]):

getvalue() should be called if something-paramer is not specified (ie.
expression something=getvalue() is evaluated), and likewise for other.
    
    
Although this would break existing code and need to be delayed to at
least 3.0 and implemented in the __future__. 

I must say I can't see the reason to not delay evalution now that we
have nested scopes. This way, even this would work:


class A:
    default_height=100
    default_width=200
    def make_picture(self, height=default_height, 
                           width=default_width):
        self.gui.do_blabla(height, width)                       
    set_default_width = classmethod(set_default_width)     

a = A()
a.make_picture()
A.default_width = 150
a.make_picture() # Now with new default width


One might argue that this could could benefit from resolving
self.default_width instead, that would still require setting
height=None and testing inside make_picture.

-- 
Stian Søiland               Being able to break security doesn't make
Trondheim, Norway           you a hacker more than being able to hotwire
http://stain.portveien.to/  cars makes you an automotive engineer. [ESR]




More information about the Python-list mailing list