By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
443,898 Members | 1,183 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 443,898 IT Pros & Developers. It's quick & easy.

Anomaly in creating class methods

P: n/a
Hi,
given below is my interaction with the interpreter.... In one case, i
have created the class method using the "famous idiom"... and in the
other, i have tried to create it outside the class definition... why
isn't the latter working ? (of course, the presence of decorators is a
different issue)....
class D: .... def f(cls):
.... print cls
.... D.f=classmethod(D.f)
D.f <bound method classobj.f of <class __main__.D at 0xb7c99f5c>> D.f() Traceback (most recent call last):
File "<stdin>", line 1, in ?
TypeError: unbound method f() must be called with D instance as first
argument (got classobj instance instead) class D: .... def f(cls):
.... print cls
.... f=classmethod(f)
.... D.f <bound method classobj.f of <class __main__.D at 0xb7c9947c>> D.f()

__main__.D

Nov 3 '05 #1
Share this Question
Share on Google+
4 Replies


P: n/a
On 3 Nov 2005 03:19:22 -0800, "venk" <ve****************@gmail.com> wrote:
Hi,
given below is my interaction with the interpreter.... In one case, i
have created the class method using the "famous idiom"... and in the
other, i have tried to create it outside the class definition... why
isn't the latter working ? (of course, the presence of decorators is a
different issue)....
class D:... def f(cls):
... print cls
... D.f=classmethod(D.f)
D.f<bound method classobj.f of <class __main__.D at 0xb7c99f5c>> D.f()Traceback (most recent call last):
File "<stdin>", line 1, in ?
TypeError: unbound method f() must be called with D instance as first
argument (got classobj instance instead) class D:... def f(cls):
... print cls
... f=classmethod(f)
... D.f<bound method classobj.f of <class __main__.D at 0xb7c9947c>> D.f()__main__.D


I think you are on very thin ice using classmethod for old-style classes.
In any case, you are not providing the same argument to classmethod
in the two examples above. I'm not sure what classmethod tries to do with
an unbound method, but it's not normal usage even in newstyle classes.
It probably just saves the callable argument as an attribute of the
classmethod instance, so the problem doesn't show until the descriptor
machinery comes into play (on attribute access and calling the bound callable).

def showcmarg(f): print 'cmarg=%r'%f; return classmethod(f) ... class D: ... def f(cls): print cls
... D.f=showcmarg(D.f) cmarg=<unbound method D.f>

Note that that was an unbound method as the arg, that gets stored in the descriptor
D.f <bound method classobj.f of <class __main__.D at 0x02EE9A1C>> D.f() Traceback (most recent call last):
File "<stdin>", line 1, in ?
TypeError: unbound method f() must be called with D instance as first argument (got classobj
tance instead)

That's just the callable (D unbound method) you gave it complaining that the descriptor is
passing the intended cls D (a classobj) instead of an instance of D to the unbound method.
class D: ... def f(cls): print cls
... f = showcmarg(f)
...
cmarg=<function f at 0x02EEAE2C>

Note that this time that was a _function_ arg, because it was picked up as a local
binding during the execution of the body of the class definition, where classmethod
was called. The function will have no demands except to match its signature when the
classmethod descriptor instance calls it with first arg of D.
D.f <bound method classobj.f of <class __main__.D at 0x02EE9A7C>> D.f() __main__.D

You could extract the normal (function) classmethod arg from the outside though:
class D: ... def f(cls): print cls
... D.f=showcmarg(D.f.im_func) cmarg=<function f at 0x02EEAD84> D.f <bound method classobj.f of <class __main__.D at 0x02EE9A4C>> D.f()

__main__.D

Suggest migrating to new style classes consistently ;-)

Regards,
Bengt Richter
Nov 3 '05 #2

P: n/a
venk <ve****************@gmail.com> wrote:
Hi,
given below is my interaction with the interpreter.... In one case, i
have created the class method using the "famous idiom"... and in the
other, i have tried to create it outside the class definition... why
isn't the latter working ? (of course, the presence of decorators is a
different issue)....


When you access D.f, you get an unbound method; if you want the
underlying function instead, use D.f.im_func. When you access f within
the class's body, you do get the underlying function -- that's all of
the difference that's biting you...
Alex
Nov 4 '05 #3

P: n/a
Cool,
i got it now... accessing thru attribute reference always
returns a bound or unbound method... so, D.f is an unbound method
whereas i want the "function" of the unbound method... ok,.... this
example and the nice explanations definitively thought me about
function, bound method (for which the function is just an attribute
accessed by im_func) and unbound method...
Also, calling classmethod on an unbound method instead of a function
is a strict no... no...
ok... nice concept...

But, i am at loss when i come to clearly understanding the difference
between new-style classes and classic classes.... (or should i post it
as new topic?).....

Nov 4 '05 #4

P: n/a
venk <ve****************@gmail.com> wrote:
Cool,
i got it now... accessing thru attribute reference always
returns a bound or unbound method... so, D.f is an unbound method
Right. Specifically, accessing through a (newstyle) class or instance
always calls the __get__ method of a descriptor [[oldstyle classes and
instances are harder to pin down -- avoid them in new code!!!]]; every
function is a descriptor, so...
whereas i want the "function" of the unbound method... ok,.... this
example and the nice explanations definitively thought me about
function, bound method (for which the function is just an attribute
accessed by im_func) and unbound method...
Great!
Also, calling classmethod on an unbound method instead of a function
is a strict no... no...
ok... nice concept...
Glad you like it.
But, i am at loss when i come to clearly understanding the difference
between new-style classes and classic classes.... (or should i post it
as new topic?).....


"Classic" classes (old-style) exist (and are the default) only for
LEGACY purposes; they exhibit a few problematic quirks. New-style
classes are more regular, fully predictable, easy to explain and to
understand. In new code, use new-style classes only (make sure every
class includes 'object' among its ancestors -- that's the simplest way).

And, sure, feel free to open another thread if you desire more
information about the several small differences between the new-style
object model and the old-style, legacy one.
Alex
Nov 4 '05 #5

This discussion thread is closed

Replies have been disabled for this discussion.