substitution of a method by a callable object

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • netimen

    substitution of a method by a callable object

    Can I substitute a method of a class by a callable object (not a
    function)? I can very easy insert my function in a class as a method,
    but an object - can't.

    I have the following:

    class Foo(object):
    pass

    class Obj(object):
    def __call__(self, obj_self):
    print 'Obj'

    def func(self):
    print 'func'

    f = Foo()
    Foo.meth = func
    f.meth() # all goes OK
    Foo.meth = Obj()
    f.meth() # I get TypeError: __call__() takes exactly 2 arguments (1
    given)
  • Terry Reedy

    #2
    Re: substitution of a method by a callable object

    netimen wrote:
    Can I substitute a method of a class by a callable object (not a
    function)? I can very easy insert my function in a class as a method,
    but an object - can't.
    Yes you can and did.
    class Foo(object):
    pass
    >
    class Obj(object):
    def __call__(self, obj_self):
    print 'Obj'
    >
    def func(self):
    print 'func'
    >
    f = Foo()
    Foo.meth = func
    f.meth() # all goes OK
    Foo.meth = Obj()
    f.meth() # I get TypeError: __call__() takes exactly 2 arguments (1
    given)
    So either remove the unused obj_self parameter from __call__ or pass
    something -- anything -- to be bound to it.
    f.meth(1) for instance, works fime (in 3.0 at least)

    Comment

    • George Sakkis

      #3
      Re: substitution of a method by a callable object

      On Oct 22, 12:13 pm, netimen <neti...@gmail. comwrote:
      Can I substitute a method of a class by a callable object (not a
      function)? I can very easy insert my function in a class as a method,
      but an object - can't.
      >
      I have the following:
      >
      class Foo(object):
          pass
      >
      class Obj(object):
          def __call__(self, obj_self):
              print 'Obj'
      >
      def func(self):
          print 'func'
      >
      f = Foo()
      Foo.meth = func
      f.meth() # all goes OK
      Foo.meth = Obj()
      f.meth() # I get TypeError: __call__() takes exactly 2 arguments (1
      given)
      You have to wrap it as an (unbound) instance method explicitly:

      from types import MethodType
      Foo.meth = MethodType(Obj( ), None, Foo)
      f.meth()

      For normal functions this seems to be done implicitly (of course you
      can do it explicitly if you want):
      >>Foo.meth = func
      >>print Foo.meth
      <unbound method Foo.func>

      George

      Comment

      • netimen

        #4
        Re: substitution of a method by a callable object

        On 22 §à§Ü§ä, 20:46, Bruno Desthuilliers
        <bdesth.quelque ch...@free.quel quepart.frwrote :
        netimen a ¨¦crit :
        >
        Can I substitute a method of a class by a callable object (not a
        function)? I can very easy insert my function in a class as a method,
        but an object - can't.
        >
        functions implement the descriptor protocol so when looked up as class
        attributes, the lookup invoke their __get__ method, which in turn
        returns a method object (which is a thin wrapper around the function,
        the class and the instance).
        >
        You can either build the method manually (as Georges explained), or make
        your own Obj class a proper descriptor:
        >
        from types import MethodType
        >
        class Obj(object):
        __name__ = "Obj" # for Method.__repr_
        >
        def __call__(self, obj_self):
        print 'Obj'
        >
        def __get__(self, instance, cls):
        return MethodType(self , instance, cls)
        >
        HTH
        thanks!

        Comment

        • Terry Reedy

          #5
          Re: substitution of a method by a callable object

          George Sakkis wrote:
          On Oct 22, 12:13 pm, netimen <neti...@gmail. comwrote:
          >
          >Can I substitute a method of a class by a callable object (not a
          >function)? I can very easy insert my function in a class as a method,
          >but an object - can't.
          >>
          >I have the following:
          >>
          >class Foo(object):
          > pass
          >>
          >class Obj(object):
          > def __call__(self, obj_self):
          > print 'Obj'
          >>
          >def func(self):
          > print 'func'
          >>
          >f = Foo()
          >Foo.meth = func
          >f.meth() # all goes OK
          >Foo.meth = Obj()
          >f.meth() # I get TypeError: __call__() takes exactly 2 arguments (1
          >given)
          >
          You have to wrap it as an (unbound) instance method explicitly:
          Nope. As the error message says, the method was called with nothing
          provided to be bound to the extraneous parameter obj_self. Either
          provide an arg, such as with f.meth(1), *or* delete obj_self and 'Obj'
          is printed, with both 2.5 and 3.0.

          Comment

          • netimen

            #6
            Re: substitution of a method by a callable object

            On 23 ÏËÔ, 00:34, Terry Reedy <tjre...@udel.e duwrote:
            George Sakkis wrote:
            On Oct 22, 12:13 pm, netimen <neti...@gmail. comwrote:
            >
            Can I substitute a method of a class by a callable object (not a
            function)? I can very easy insert my function in a class as a method,
            but an object - can't.
            >
            I have the following:
            >
            class Foo(object):
            š š pass
            >
            class Obj(object):
            š š def __call__(self, obj_self):
            š š š š print 'Obj'
            >
            def func(self):
            š š print 'func'
            >
            f = Foo()
            Foo.meth = func
            f.meth() # all goes OK
            Foo.meth = Obj()
            f.meth() # I get TypeError: __call__() takes exactly 2 arguments (1
            given)
            >
            You have to wrap it as an (unbound) instance method explicitly:
            >
            Nope. šAs the error message says, the method was called with nothing
            provided to be bound to the extraneous parameter obj_self. šEither
            provide an arg, such as with f.meth(1), *or* delete obj_self and 'Obj'
            is printed, with both 2.5 and 3.0.
            OK, I have implemented Bruno Desthuilliers example. But there is
            another question: can I having a method determine if it is an instance
            of given class. So:

            class Obj(object):
            __name__ = "Obj" # for Method.__repr_

            def __call__(self, obj_self):
            print 'Obj'

            def __get__(self, instance, cls):
            return MethodType(self , instance, cls)

            class Foo(object):
            pass

            Foo.meth = Obj()

            ## in some another place of code
            if isinstance(Foo. meth, Obj): # doesn't work because type(Foo.meth) is
            now 'instancemethod '
            ...

            Can I determine that?

            Comment

            • netimen

              #7
              Re: substitution of a method by a callable object

              On 23 §à§Ü§ä, 00:26, Bruno Desthuilliers
              <bdesth.quelque ch...@free.quel quepart.frwrote :
              netimen a ¨¦crit :
              (snip)
              >
              OK, I have implemented Bruno Desthuilliers example. But there is
              another question: can I having a method determine if it is an instance
              of given class. So:
              >
              As the name imply, a method is usually, well, an instance of type
              'method' !-)
              >
              >
              >
              class Obj(object):
              (snip)
              >
              class Foo(object):
              pass
              >
              Foo.meth = Obj()
              >
              ## in some another place of code
              if isinstance(Foo. meth, Obj): # doesn't work because type(Foo.meth) is
              now 'instancemethod '
              >
              Indeed. I suppose what you want is to know if the callable wrapped by
              the method is an instance of Obj ?
              >
              >
              >
              Can I determine that?
              >
              Yeps. Test the im_func attribute of the method:
              >
              if isinstance(Foo. meth.im_func, Obj): print "yadda"
              >
              But you'd better put this in a try/except block, because a callable
              attribute of a class is not necessarily a method - and so it may not
              have an im_func attribute.
              >
              Also, may I ask why you want to check this ? Not that it's necessarily
              wrong, but real use case for typechecking are pretty rare.
              Thanks! I have wasted much time playing with different Foo.meth trying
              to get to Obj through them. But im_func was one of the fields I
              haven't checked )

              Indeed, I have managed already without that. The task was to
              substitute __str__ method by a complex formatter. It called a low-
              level formatter, a function wich returned simple str(self). That
              function could be called with objects with substituted formatters and
              with simple objects. So to avoid recursion I wanted to check wether
              the formatter of my object was substituted.

              Comment

              Working...