Diez B. Roggisch <[EMAIL PROTECTED]> wrote: ... > > If there a good reason that the __get__ of a boundmethod does not > > create a new boundmethod wrapper over the first boundmethod? > > I already gave you the good reason:
Hmmm, not sure the code below is ``a good reason'' to avoid changing the __get__ behavior of boundmethods come Python 3.0 time. Assume all classes are newstyle (they'll be, in 3.0), not that it matters here (I think): > class A: > def callback(self, arg): > print self, arg > > def callback(arg): > print arg > > class DoSomethingWithCallback: > def __init__(self, cb): > self.cb = cb Here we're setting an INSTANCE attribute, > def run(self): > for i in xrange(100): > self.cb(i) ...and here we're fetching it back. So, it doesn't matter if the cb argument is a descriptor of whatever variant -- it must be callable, and that's all we ask of it. IOW, cb.__get__ -- whether it exists at all, and what it does -- just doesn't *matter*; cb.__call__ is all that does matter. > u = DoSomethingWithCallback(A().callback) > v = DoSomethingWithCallback(callback) > > # would crash if your suggestion worked > u.run() > v.run() I don't think there would be any crash, because the idea is about changing some __get__ behavior, NOT any __call__ behavior, and no __get__ is involved in this example. If strong use cases exist for a boundmethod's __get__ keeping its current behavior (apart from the obvious backwards compatibility issues which mean that any change will have to wait for 3.0), I don't think this can be one. > Bound methods aren't a general purpose currying scheme - they exist sorely > for the OO-style implicit first argument. That they exist at all is a great > difference to e.g. C++, where you can't pass callbacks around that are > instance methods. This is historically true. However, this historical fact is not necessarily a reason for keeping the current lower-power behavior of boundmethods, when 3.0 allows breaking backwards compatibility. > If you are after currying - look at the cookbook, there are recipes for > that. Sure, I wrote some of them;-). But since we're talking about future prospects, I think the PEP on partial application is more relevant than the current pure-Python workarounds. They _are_ workarounds, btw -- partial application, aka currying, is an important general idea; it can be implemented in Python, but it's not directly part of it. The PEP's idea is to have that concept directly implemented. Actually, I believe that if you call new.instancemethod you CAN already get that effect -- let's see...: >>> import new >>> curry = new.instancemethod >>> def f(a, b, c): print a, b, c ... >>> x = curry(curry(f, 23, object), 45, object) >>> x(67) 23 45 67 Yep -- just fine (in __call__ terms). Not so in __get__ terms: >>> class X(object): pass ... >>> X.zap = x >>> y = X() >>> y.zap() Traceback (most recent call last): File "<stdin>", line 1, in ? TypeError: f() takes exactly 3 arguments (2 given) So, for generic currying (in the original sense: prebinding the FIRST argument of any callable), new.instancemethod is OK (even though you have to pass a third argument of 'object', no big deal), and you can call it repeatedly. We're only missing a descriptor with a __get__ that does this appropriately when you set such a ``curried'' callable as a class attribute. I'm not sure if the best approach is to change boundmethods' own __get__, or to have another descriptor for the purpose: >>> class binder(object): ... def __init__(self, callable): self.callable = callable ... def __get__(self, obj, cls): return curry(self.callable, obj, cls) ... >>> X.zap = binder(x) >>> y.zap() 23 45 <__main__.X object at 0x402dfa8c> This ``binder'' approach would have the advantage of allowing ANY callable whatsoever, e.g.: >>> X.__divmod__ = lambda self, other: (self, other) >>> divmod(y, 23) (<__main__.X object at 0x402dfa8c>, 23) >>> X.dm = binder(divmod) >>> y.dm(23) (<__main__.X object at 0x402dfa8c>, 23) >>> Of course, a custom metaclass could easily wrap 'binder' around any class attributes which are callable but aren't descriptors, to get the same effect more transparently. Hmmmm -- the tradeoffs aren't clear to me at this time. That's exactly what the PEP process is for... ensure that any tradeoffs ARE discussed in depth before any change is made. Alex -- http://mail.python.org/mailman/listinfo/python-list