Method binding confusion

Discussion in 'Python' started by A B Carter, May 3, 2004.

  1. A B Carter

    A B Carter Guest

    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
    A B Carter, May 3, 2004
    #1
    1. Advertising

  2. A B Carter

    Peter Otten Guest

    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
    Peter Otten, May 3, 2004
    #2
    1. Advertising

  3. 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.
    Andrew Bennetts, May 3, 2004
    #3
  4. A B Carter

    Eric Brunel Guest

    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
    Eric Brunel, May 3, 2004
    #4
  5. A B Carter

    Peter Otten Guest

    Sorry, was Re: Method binding confusion

    Sorry, my above answer has several errors, please discard.

    Peter
    Peter Otten, May 3, 2004
    #5
  6. A B Carter

    Peter Otten Guest

    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
    Peter Otten, May 3, 2004
    #6
  7. A B Carter

    Sridhar R Guest

    Bound and Unbound methods are different and server different purposes.
    See documentation for more details.

    (A B Carter) wrote in message news:<>...
    > 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
    Sridhar R, May 3, 2004
    #7
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Jordan
    Replies:
    2
    Views:
    2,530
    Jordan
    Feb 10, 2004
  2. Replies:
    2
    Views:
    1,050
  3. Amit
    Replies:
    6
    Views:
    13,791
    Assimalyst
    Oct 24, 2006
  4. Robert Brewer

    RE: Method binding confusion

    Robert Brewer, May 3, 2004, in forum: Python
    Replies:
    14
    Views:
    505
    David MacQuigg
    May 26, 2004
  5. Replies:
    2
    Views:
    857
    Kevin Grover
    Oct 20, 2006
Loading...

Share This Page