mutable default parameter problem [Prothon]

Dave Brueck dave at pythonapocrypha.com
Thu Jun 17 17:01:01 CEST 2004


Mark wrote:
> >> In Prothon:
> >>     def foo(x):
> >>             print foo.list.append!(x)
> >>     foo.list = []
> >>
> >> (Sorry. I couldn't resist bragging.)
> >
> > About what?
> >
> > Python 2.3.3 (#51, Dec 18 2003, 20:22:39) [MSC v.1200 32 bit (Intel)]
> >  >>> def foo(x):
> > ...   foo.list.append(x)
> > ...   print foo.list
> > ...
> >  >>> foo.list = []
> >  >>> foo('test')
> > ['test']
> >
> > (Oh, did you mean bragging about how a hard-to-see exclamation
> > mark causes append() to return the sequence?  I thought
> > maybe it was about the function attribute or something.)
>
> Actually, I didn't know if the function attribute assignment outside the
> function would work in Python or not.  I guess I'll know better than to
try
> to play one-upmanship with Python next time.  I did say I was sorry :-)
>
> FYI: It's not that the exclamation mark causes append to return the
> sequence.  The exclamation mark is always there and the sequence is always
> returned.  The exclamation mark is the universal symbol for in-place
> modification. This is straight from Ruby and solves the problem that
caused
> Guido to not allow sequences to be returned.  And, yes, I do think that's
> worth bragging about ;-)

Wait, so is the exclamation point required or not? IOW, say you have a class
like this:

class List(list):
  def append(self, what):
    list.append(self, what)
    return self

a = List()
b = a.append(5)

So in the call to append, is it a.append!(5) or just a.append(5) ? If it's
the former, then does the compiler detect that it's required because the
function returns 'self' or is the determining factor something else?

Or, does the append method not really return anything, and the language
takes care of substituting in the object? (in which case, does that mean you
can override the return value by adding '!' - such that z=foo.bar!() ignores
the return value of bar and z references foo?)

Personally, I don't like the modify-in-place-and-return-the-object
'feature' - it's not needed _that_ often, but more importantly, it makes the
code harder to read (to me at least). For example, it makes sense that
append() doesn't normally return a value. If you told me it did return
something, my first guess would be that the return value is the new length
of the list (I guess I find it too easy to overlook the presence of '!').

For something like list.sort(), *if* there's a return value I'd expect it to
be a sorted _copy_ of the list, certainly not the list itself. Even with the
extra punctuation, it seems likely that you'd have bugs of the form:

a = b.sort!()
# do something destructive to 'a'
# do something with b, expecting it to be the original

Or, maybe you'd get bugs of this form:

w = x.y.z!()
# Do something with w, thinking it's a reference to x

Not that you'd go very far before discovering the bug, but it'd probably
annoy the guy reading the code. :)

If you want the object, then use the object (i.e. if you want to print the
list, then print the list), but making tricked out method calls that return
themselves just to save a line or two of code sacrifices clarity for too
little benefit. Ah well, I guess that's why I use Python, huh? :)

Best of luck,
Dave





More information about the Python-list mailing list