Anomaly in creating class methods

V

venk

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)........ def f(cls):
.... print cls
....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).... def f(cls):
.... print cls
.... f=classmethod(f)
....__main__.D
 
B

Bengt Richter

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)....
... def f(cls):
... print cls
...
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)
... def f(cls):
... print cls
... f=classmethod(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 f(cls): print cls
... cmarg=<unbound method D.f>

Note that that was an unbound method as the arg, that gets stored in the descriptor
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.
... 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.
__main__.D

You could extract the normal (function) classmethod arg from the outside though:
... def f(cls): print cls
... __main__.D

Suggest migrating to new style classes consistently ;-)

Regards,
Bengt Richter
 
A

Alex Martelli

venk said:
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
 
V

venk

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?).....
 
A

Alex Martelli

venk said:
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
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Forum statistics

Threads
474,270
Messages
2,571,341
Members
48,031
Latest member
rashmi16

Latest Threads

Top