Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Python > Confused with methods

Reply
Thread Tools

Confused with methods

 
 
Diez B. Roggisch
Guest
Posts: n/a
 
      02-07-2005
> HOWEVER, what I ask is WHY don't we set the tp_descr_get of
> the boundmethod object to be the same as the func_descr_get???
> Or WHY do they *have* to differ in this specific part?
>
> I quickly looked at the source of python and it seems that a
> one-liner would be enough to enable this. So it's not that it
> would be hard to implement it, or inefficient.
>
> A bound method would *still* be a boundmethod.
> We could additionally have:
>
> >>>type(x)

> <boundmethod of <boundmethod of <boundmethod of....<__main__.A
> instance at 0x>>>
>
> 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:

class A:
def callback(self, arg):
print self, arg

def callback(arg):
print arg

class DoSomethingWithCallback:
def __init__(self, cb):
self.cb = cb

def run(self):
for i in xrange(100):
self.cb(i)

u = DoSomethingWithCallback(A().callback)
v = DoSomethingWithCallback(callback)

# would crash if your suggestion worked
u.run()
v.run()


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.

If you are after currying - look at the cookbook, there are recipes for
that.
--
Regards,

Diez B. Roggisch
 
Reply With Quote
 
 
 
 
Antoon Pardon
Guest
Posts: n/a
 
      02-07-2005
Op 2005-02-06, Alex Martelli schreef <>:
>
>> Isn't that inconsistent?

>
> That Python has many callable types, not all of which are descriptors?
> I don't see any inconsistency there. Sure, a more generalized currying
> (argument-prebinding) capability would be more powerful, but not more
> consistent (there's a PEP about that, I believe).


I think python is a bit inconsistent here, by using 'def' for
two different things. I think it would have been more consistent
if def always produces a function to be used as such and that
methods had there own keyword. That would make the magic of
bound methods more explicit.

--
Antoon Pardon
 
Reply With Quote
 
 
 
 
Alex Martelli
Guest
Posts: n/a
 
      02-07-2005
Diez B. Roggisch <> 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
 
Reply With Quote
 
Alex Martelli
Guest
Posts: n/a
 
      02-07-2005
Antoon Pardon <> wrote:

> Op 2005-02-06, Alex Martelli schreef <>:
> >
> >> Isn't that inconsistent?

> >
> > That Python has many callable types, not all of which are descriptors?
> > I don't see any inconsistency there. Sure, a more generalized currying
> > (argument-prebinding) capability would be more powerful, but not more
> > consistent (there's a PEP about that, I believe).

>
> I think python is a bit inconsistent here, by using 'def' for
> two different things.


It doesn't.

> I think it would have been more consistent
> if def always produces a function


It does.

def g(self): pass
class A(object):
f = g

class B(object):
def f(self): pass

class C(object): pass
C.f = g

class D(object):
f = B.f

These four classes are essentially equivalent. def always produces a
function object and binds it to the name coming after keyword 'def'.
Any such function object, no matter how produced and how bound hither
and thither, always behaves in exactly the same way.

You're free to like or dislike this arrangement, but calling it
"inconsistent" is a madman's folly, as it is TOTALLY consistent.


Alex

 
Reply With Quote
 
John Lenton
Guest
Posts: n/a
 
      02-07-2005
On Mon, Feb 07, 2005 at 03:24:11PM +0100, Alex Martelli wrote:
> def always produces a
> function object and binds it to the name coming after keyword 'def'.
> Any such function object, no matter how produced and how bound hither
> and thither, always behaves in exactly the same way.


This isn't exactly true:

>>> class C(object):

... def __new__(*a): pass
...
>>> C.__new__

<function __new__ at 0x40088d4c>
>>> class D(object): pass

...
>>> def __new__(*a): pass

...
>>> D.__new__ = __new__
>>> D.__new__

<unbound method D.__new__>

of course, __new__ is special-cased (*some*body should've read "import
this", especially the part "explicit is better than implicit").

--
John Lenton () -- Random fortune:
Al freír será el reír.

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.5 (GNU/Linux)

iD8DBQFCB3//gPqu395ykGsRAj+oAKCTuBPtru/i2eRKGmglq9V3xD7ePACeNPBB
a1jyxnxo1mQp9372+wimRnQ=
=bDQb
-----END PGP SIGNATURE-----

 
Reply With Quote
 
Antoon Pardon
Guest
Posts: n/a
 
      02-07-2005
Op 2005-02-07, Alex Martelli schreef <>:
> Antoon Pardon <> wrote:
>
>> Op 2005-02-06, Alex Martelli schreef <>:
>> >
>> >> Isn't that inconsistent?
>> >
>> > That Python has many callable types, not all of which are descriptors?
>> > I don't see any inconsistency there. Sure, a more generalized currying
>> > (argument-prebinding) capability would be more powerful, but not more
>> > consistent (there's a PEP about that, I believe).

>>
>> I think python is a bit inconsistent here, by using 'def' for
>> two different things.

>
> It doesn't.
>
>> I think it would have been more consistent
>> if def always produces a function

>
> It does.
>
> def g(self): pass
> class A(object):
> f = g
>
> class B(object):
> def f(self): pass
>
> class C(object): pass
> C.f = g
>
> class D(object):
> f = B.f
>
> These four classes are essentially equivalent. def always produces a
> function object and binds it to the name coming after keyword 'def'.
> Any such function object, no matter how produced and how bound hither
> and thither, always behaves in exactly the same way.
>
> You're free to like or dislike this arrangement, but calling it
> "inconsistent" is a madman's folly, as it is TOTALLY consistent.


Yes it is inconsistent with the rest of python. That you found
a subset in which it is consistent doesn't change that.

And what if you do:

c = C()
c.f = g


The fact that a function in a class performs a lot of magic if
it is called through an instance, that isn't performed otherwise,
makes python inconsistent here. You may like the arrangement
(and it isn't such a big deal IMO) but that doesn't make it consistent.

--
Antoon Pardon
 
Reply With Quote
 
John Lenton
Guest
Posts: n/a
 
      02-07-2005
On Mon, Feb 07, 2005 at 02:53:49PM +0000, Antoon Pardon wrote:
> The fact that a function in a class performs a lot of magic if
> it is called through an instance, that isn't performed otherwise,
> makes python inconsistent here. You may like the arrangement
> (and it isn't such a big deal IMO) but that doesn't make it consistent.


I vote for accepting the fact (it goes with the "practicality beats
purity" bit, because otherwise all our methods would have to start
with an @instancemethod). This doesn't justify (IMVVHO) a new keyword,
like you (was it you?) seemed to imply (do you really mean for
instancemethod (or somesuch) and classmethod to become keywords?). I
think it's fine the way it is: there's an implicit @instancemethod,
and @staticmethod (which you'd have be the default if I read you
right) has to be explicit, when in classes. I think __new__ being an
exception to this is a (minor) wart, in fact it feels like premature
optimization (how many __new__s do you write, that you can't stick a
@staticmethod in front of them?

--
John Lenton () -- Random fortune:
Fun Facts, #14:
In table tennis, whoever gets 21 points first wins. That's how
it once was in baseball -- whoever got 21 runs first won.

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.5 (GNU/Linux)

iD8DBQFCB4gKgPqu395ykGsRAnfEAJ9Dzqh/5WxP3W2C6EZKdEJ3Dk9CogCeOrDz
Se4r4OBFagG6F6tbnxOUhA0=
=feKR
-----END PGP SIGNATURE-----

 
Reply With Quote
 
Antoon Pardon
Guest
Posts: n/a
 
      02-07-2005
Op 2005-02-07, John Lenton schreef <>:
>
>
> --cvVnyQ+4j833TQvp
> Content-Type: text/plain; charset=us-ascii
> Content-Disposition: inline
> Content-Transfer-Encoding: quoted-printable
>
> On Mon, Feb 07, 2005 at 02:53:49PM +0000, Antoon Pardon wrote:
>> The fact that a function in a class performs a lot of magic if
>> it is called through an instance, that isn't performed otherwise,
>> makes python inconsistent here. You may like the arrangement
>> (and it isn't such a big deal IMO) but that doesn't make it consistent.

>
> I vote for accepting the fact (it goes with the "practicality beats
> purity" bit,


But before one can produce the "practicality beats purity" argument,
one has to accept this isn't pure. That was all I was saying here,
python is not consistent/pure here. Now there can be good arguments
to have this that offset the inconsistency, but the python people
shouldn't then try to argue that it is consistent anyway.

> because otherwise all our methods would have to start
> with an @instancemethod). This doesn't justify (IMVVHO) a new keyword,
> like you (was it you?) seemed to imply (do you really mean for
> instancemethod (or somesuch) and classmethod to become keywords?). I
> think it's fine the way it is: there's an implicit @instancemethod,
> and @staticmethod (which you'd have be the default if I read you
> right) has to be explicit, when in classes.


I'm not saying I would have it so, I'm saying that would be the
pure/consistent way to do it.

--
Antoon Pardon
 
Reply With Quote
 
Alex Martelli
Guest
Posts: n/a
 
      02-07-2005
Antoon Pardon <> wrote:

> Yes it is inconsistent with the rest of python. That you found
> a subset in which it is consistent doesn't change that.
>
> And what if you do:
>
> c = C()
> c.f = g
>
>
> The fact that a function in a class performs a lot of magic if
> it is called through an instance, that isn't performed otherwise,
> makes python inconsistent here. You may like the arrangement
> (and it isn't such a big deal IMO) but that doesn't make it consistent.


Any descriptor (be it a function or otherwise) has its __get__ method
called, when _accessed_ by attribute syntax, if and only if that
descriptor is in a class. _ALL_ of Python is perfectly consistent on
this point, and if I didn't already know the kind of crazy and obviously
false assertions that you post *QUITE* consistently, I would be
astonished to see you claim otherwise. Knowing your posts, this latest
idiocy is perfectly "par for the course".

"A lot of magic" is simply a stupid and imprecise way to describe "the
__get__ method gets called". Saying that any of this happens when the
function is CALLED is a definitely more serious mistake, since it's
absolutely obvious that the __get__ method is called when the function
(or any other attribute) is *ACCESSED* -- the call operation (on
whatever object __get__ returns) happens AFTERWARDS.

Why you, and a few other habitual trolls, keep lowering the signal to
noise ratio of this newsgroup with your blatherings, I don't know; I'm
sure this behavior must be giving you guys some kind of satisfaction.
Whether the damage you do to the clarity of the issues, and to the
understanding of newbies who are unfortunate enough to read and trust
the many imprecise and/or utterly false assertions you keep making, with
totally unjustified airs of competence, is part of your jollies, or just
a side effect you don't care a whit about, I don't know either. Guess
I'll just killfile you for another month now -- wish MacSOUP had a
simple way to to permanent killfiling, since it's pretty obvious by now
that it's quite unlikely you'll even post anything worthwhile at all.


Alex
 
Reply With Quote
 
Alex Martelli
Guest
Posts: n/a
 
      02-07-2005
John Lenton <> wrote:

> I think __new__ being an
> exception to this is a (minor) wart, in fact it feels like premature
> optimization (how many __new__s do you write, that you can't stick a
> @staticmethod in front of them?


I personally think it's quite reasonable for Python's infrastructure to
consider each special name specially -- that's what the double
underscores before and after are FOR, after all. Since __new__ MUST be
a staticmethod, and there's no use case for it ever being otherwise, it
seems quite sensible for the default metaclass to MAKE it a staticmethod
(and otherwise treat it specially, as it needs to be). I don't see what
optimization has to do with it (quite apart from the fact that __new__
was introduced before the splatsyntax for decorators, so that rather
than sticking anything in front the alternative would have been to
demand serious boilerplate, a '__new__ = staticmethod(__new__)' after
every definition of such a method). Reducing boilerplate with no ill
effects whatsoever seems quite a worthy goal to me, when reachable.


Alex
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Is there a way to find the class methods of a class, just like'methods' finds the instance methods? Kenneth McDonald Ruby 5 09-26-2008 03:09 PM
Top-Up Methods - Finarea (Voipcheap, internetcalls, etc.) et. al., VOIP Services Question - Top-up Methods News Reader UK VOIP 0 04-10-2006 02:41 PM
Why Petshop Changed all static methods to instance methods when upgrading from version 3.0 to version 3.1? Neo ASP .Net 1 01-07-2005 01:46 AM
Really confused about authorization/authentication methods in ASP.Net STom ASP .Net Security 2 08-07-2003 08:45 AM
Re: Templates and friends and template methods with private methods. Buster Copley C++ 5 07-07-2003 12:50 AM



Advertisments