Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Python > Method binding confusion

Reply
Thread Tools

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
 
Reply With Quote
 
 
 
 
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

 
Reply With Quote
 
 
 
 
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.

See http://users.rcn.com/python/download/Descriptor.htm, particularly the
section on Functions and Methods.

-Andrew.


 
Reply With Quote
 
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> -
PragmaDev : Real Time Software Development Tools - http://www.pragmadev.com

 
Reply With Quote
 
Peter Otten
Guest
Posts: n/a
 
      05-03-2004
Sorry, my above answer has several errors, please discard.

Peter
 
Reply With Quote
 
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


 
Reply With Quote
 
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

 
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
GridView binding - how to stop initial binding Amit ASP .Net 6 10-24-2006 08:06 AM
pywin32 COM sort in Excel (late binding fails, early binding works) (+py2exe) kogrover@gmail.com Python 2 10-20-2006 04:08 PM
Binding to a Repeater in Codebehind...a little confusion. nobody@somewhere.com ASP .Net 2 03-22-2005 06:15 AM
RE: Method binding confusion Robert Brewer Python 14 05-26-2004 03:31 AM
Data Binding - using inline code vs. functions vs. straight binding Jordan ASP .Net 2 02-10-2004 08:32 PM



Advertisments