Velocity Reviews > Method binding confusion

Method binding confusion

A B Carter
Guest
Posts: n/a

 05-03-2004
I'm a bit confused by the behavior of the following code:

import math
import myModule

class Klass(object):
def doOperation(self, x, y):
return self.operator(x, y)

class KlassMath(Klass):
operator = math.pow

class KlassMyModule(Klass):
operator = myModule.pow

km = KlassMath()
kmy = KlassMyModule()

km.doOperation(2,4)
km.doOperation(2,4)

The last call fails with "TypeError: takes exactly 2 argumetns (3
given)" I understand that in KlassMyModule the operator is being
treated as a method and a reference to the class instance is being
past as the first argument. And I also understand that Python is
treating a function from the standard math libary differently from a
function I defined in my own module. What I don't understand is why.

A B Carter

Peter Otten
Guest
Posts: n/a

 05-03-2004
A B Carter wrote:

> I'm a bit confused by the behavior of the following code:
>
>
> import math
> import myModule
>
> class Klass(object):
> def doOperation(self, x, y):
> return self.operator(x, y)
>
> class KlassMath(Klass):
> operator = math.pow
>
> class KlassMyModule(Klass):
> operator = myModule.pow
>
> km = KlassMath()
> kmy = KlassMyModule()
>
> km.doOperation(2,4)
> km.doOperation(2,4)

Should that be kmy.doOperation(2,4)? Please cut and paste actual code. (The
same goes for the tracebacks)

> The last call fails with "TypeError: takes exactly 2 argumetns (3
> given)" I understand that in KlassMyModule the operator is being
> treated as a method and a reference to the class instance is being
> past as the first argument. And I also understand that Python is
> treating a function from the standard math libary differently from a
> function I defined in my own module. What I don't understand is why.

Assuming that myModule.pow (which you do not to provide) is a function that
takes two arguments, all these will fail:

kmy.doOperation(2, 4)
kmy.operator(2, 4)
km.doOperation(2, 4)
km.operator(2, 4)

If you want to avoid the automatic addition of self, use staticmethod:

>>> def mypow(a, b):

.... return "%s ** %s" % (a, b)
....
>>> class MyClass:

.... operator = staticmethod(mypow)
....
>>> MyClass().operator(2, 4)

'2 ** 4'
>>>

Peter

Andrew Bennetts
Guest
Posts: n/a

 05-03-2004
On Sun, May 02, 2004 at 11:57:26PM -0700, A B Carter wrote:
> I'm a bit confused by the behavior of the following code:

[...]
>
> The last call fails with "TypeError: takes exactly 2 argumetns (3
> given)" I understand that in KlassMyModule the operator is being
> treated as a method and a reference to the class instance is being
> past as the first argument. And I also understand that Python is
> treating a function from the standard math libary differently from a
> function I defined in my own module. What I don't understand is why.

Builtin functions aren't descriptors; in particular, they don't have the
method-wrapping magic in their __get__ that ordinary (i.e. pure-python)
function objects do.

section on Functions and Methods.

-Andrew.

Eric Brunel
Guest
Posts: n/a

 05-03-2004
Peter Otten wrote:
> A B Carter wrote:
>
>
>>I'm a bit confused by the behavior of the following code:
>>
>>
>>import math
>>import myModule
>>
>>class Klass(object):
>> def doOperation(self, x, y):
>> return self.operator(x, y)
>>
>>class KlassMath(Klass):
>> operator = math.pow
>>
>>class KlassMyModule(Klass):
>> operator = myModule.pow
>>
>>km = KlassMath()
>>kmy = KlassMyModule()
>>
>>km.doOperation(2,4)
>>km.doOperation(2,4)

>
>
> Should that be kmy.doOperation(2,4)? Please cut and paste actual code. (The
> same goes for the tracebacks)
>
>
>>The last call fails with "TypeError: takes exactly 2 argumetns (3
>>given)" I understand that in KlassMyModule the operator is being
>>treated as a method and a reference to the class instance is being
>>past as the first argument. And I also understand that Python is
>>treating a function from the standard math libary differently from a
>>function I defined in my own module. What I don't understand is why.

>
>
> Assuming that myModule.pow (which you do not to provide) is a function that
> takes two arguments, all these will fail:
>
> kmy.doOperation(2, 4)
> kmy.operator(2, 4)
> km.doOperation(2, 4)
> km.operator(2, 4)
>
> If you want to avoid the automatic addition of self, use staticmethod:
>
>
>>>>def mypow(a, b):
>>>

> ... return "%s ** %s" % (a, b)
> ...
>
>>>>class MyClass:
>>>

> ... operator = staticmethod(mypow)
> ...
>
>>>>MyClass().operator(2, 4)
>>>

> '2 ** 4'
>
>
> Peter

I can reproduce the OP's behaviour with old-style classes in Python 2.1.1:

>>> class C:

.... def op(self, x, y):
.... return self.operator(x, y)
....
>>> import math
>>> class C1(C):

.... operator = math.pow
....
>>> o1 = C1()
>>> o1.op(2, 3)

8.0
>>> def myPow(x, y): return '%s ** %s' % (x, y)

....
>>> class C2(C):

.... operator = myPow
....
>>> o2 = C2()
>>> o2.op(2, 3)

Traceback (most recent call last):
File "<stdin>", line 1, in ?
File "<stdin>", line 3, in op
TypeError: myPow() takes exactly 2 arguments (3 given)

I also cannot understand the difference between C1 and C2: math.pow and myPow
are both functions with two parameters, so why does the first work and not the
second? Or was it an "unwanted feature" that was removed in a later version?

I also have some difficulty to understand the "automatic addition of self" you
mention. In what case is it needed? I would have sworn the two classes worked...
--
- Eric Brunel <eric (underscore) brunel (at) despammed (dot) com> -

Peter Otten
Guest
Posts: n/a

 05-03-2004

Peter

Peter Otten
Guest
Posts: n/a

 05-03-2004
Eric Brunel wrote:

> I can reproduce the OP's behaviour with old-style classes in Python 2.1.1:

Me too, with new-style classes in Python 2.3.3:

<kmy.py>
import math
#import myModule

def mypow(x, y):
return "%s ** %s" % (x, y)

class Klass(object):
def doOperation(self, x, y):
return self.operator(x, y)

class KlassMath(Klass):
operator = math.pow

class KlassMyModule(Klass):
operator = mypow #myModule.pow

km = KlassMath()
kmy = KlassMyModule()

print km.doOperation(2,4)
print kmy.doOperation(2,4)
</kmy.py>

Running the above:
\$ python -V
Python 2.3.3
\$ python kmy.py
16.0
Traceback (most recent call last):
File "kmy.py", line 21, in ?
print kmy.doOperation(2,4)
File "kmy.py", line 9, in doOperation
return self.operator(x, y)
TypeError: mypow() takes exactly 2 arguments (3 given)

> I also cannot understand the difference between C1 and C2: math.pow and
> myPow are both functions with two parameters, so why does the first work
> and not the second? Or was it an "unwanted feature" that was removed in a
> later version?
>
> I also have some difficulty to understand the "automatic addition of self"
> you mention. In what case is it needed? I would have sworn the two classes
> worked...

>>> class A:

.... pass
....
>>> def method(*args):

.... print args
....
>>> A.m = method
>>>
>>> A().m(1,2)

(<__main__.A instance at 0x40296bac>, 1, 2)

See? Although defined outside the class, method() is called with 3
parameters. *I* could have sworn that _that_ would always happen. But:

>>> import math
>>> A.m = math.pow
>>> A().m(1,2)

1.0
>>>

Now I am as confused as you and the OP

Peter

Sridhar R
Guest
Posts: n/a

 05-03-2004
Bound and Unbound methods are different and server different purposes.
See documentation for more details.

http://www.velocityreviews.com/forums/(E-Mail Removed) (A B Carter) wrote in message news:<(E-Mail Removed). com>...
> I'm a bit confused by the behavior of the following code:
>
>
> import math
> import myModule
>
> class Klass(object):
> def doOperation(self, x, y):
> return self.operator(x, y)
>
> class KlassMath(Klass):
> operator = math.pow
>
> class KlassMyModule(Klass):
> operator = myModule.pow
>
> km = KlassMath()
> kmy = KlassMyModule()
>
> km.doOperation(2,4)
> km.doOperation(2,4)
>
>
> The last call fails with "TypeError: takes exactly 2 argumetns (3
> given)" I understand that in KlassMyModule the operator is being
> treated as a method and a reference to the class instance is being
> past as the first argument. And I also understand that Python is
> treating a function from the standard math libary differently from a
> function I defined in my own module. What I don't understand is why.
>
> A B Carter

 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 OffTrackbacks are On Pingbacks are On Refbacks are Off Forum Rules

 Similar Threads Thread Thread Starter Forum Replies Last Post Amit ASP .Net 6 10-24-2006 08:06 AM kogrover@gmail.com Python 2 10-20-2006 04:08 PM nobody@somewhere.com ASP .Net 2 03-22-2005 06:15 AM Robert Brewer Python 14 05-26-2004 03:31 AM Jordan ASP .Net 2 02-10-2004 08:32 PM