* 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.
It works as designed. The default parameter value bindings are made a def time.
If you want to do them at call time, the idiom is
def f(d=None):
if d is None: d = []
d.append(0)
print d
Why not evaluate the parameter lists at calltime instead of definition
time? This should work the same way as lambdas.
Lambdas do work the same as defs, except for the automatic name binding
and the limitation to an expression as the body.
f = lambda: []
a=f()
b=f()
a.append(1)
print a, b
[1] []
The comparable def code to your lambda would be
def f(): return []
The above is misguiding attention away from your point, IMO.
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 might be an interesting concise spelling to accomplish what the following does:
(BTW, you need a self for normal methods)
... def __init__(self, fun): self.fun = fun
... ... def blapp(self, something=Defer(lambda: getvalue()), other=Defer(lambda:[])):
... if isinstance(something, Defer): something = something.fun()
... if isinstance(other, Defer): other = other.fun()
... print something, other
...
>>> def getvalue(): return 'gotten_value' ...
>>> sc = SomeClass()
>>> sc.blapp() gotten_value []
>>> sc.blapp(1) 1 []
>>> sc.blapp('one', 'two')
one two
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.
Yes, messy. ISTM better to let them be defined in the same scope
as the def, as in my example above.
(Note that default-parameters-lambdas by today does NOT resolve this way:
... ting = 15
... def fix(self, per=lambda: ting):
... print per()
...
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
Right, though you could get the functionality if you wanted to.
Finally, things could also be done like this, to avoid confusion to all
those new folks (our main goal):
If they're confused because their preconceptions are filtering out
anything discordant, pandering to them would not serve the language.
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.
No. I like your version with the lambda-colons much better.
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
Are you sure you counted your negatives there? ;-)
have nested scopes. This way, even this would work:
You're assuming default_height will refer to A.default_height
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)
IMO better:
class A:
default_height=100
default_width=200
def make_picture(self, height: A.default_height,
width: A.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.
Or maybe have the implict lambda have an implicit self arg bound like a method
if it is the default arg of a method, ie., so you could write
class A:
default_height=100
default_width=200
def make_picture(self, height: self.default_height,
width: self.default_width):
self.gui.do_blabla(height, width)
Then when the function was called, it would be like getting an implicit something like
... default_height=100
... default_width=200
... def make_picture(self, height=Defer(lambda self: self.default_height),
... width=Defer(lambda self: self.default_width)):
... if isinstance(height, Defer): height = height.fun.__get__(self)()
... if isinstance(width, Defer): width = width.fun.__get__(self)()
... self.gui.do_blabla(height, width)
... class gui(object): # something to catch the above ;-/
... def do_blabla(h,w): print 'h=%r, w=%r'%(h,w)
... do_blabla = staticmethod(do_blabla)
... h='one', w='two'
Obviously the nested class gui is just to make the self.gui.do_blabla call work as spelled ;-)
I doubt if this is going to make it, but I think it's feasible without backwards breakage.
Write a PEP if you want to pursue something like that, but don't get overexcited ;-)
Regards,
Bengt Richter