[Pyrex] pyrex functions to replace a method (Re: replace a method in class: how?)

Lenard Lindstrom len-l at telus.net
Wed Jun 28 20:40:15 CEST 2006


On 28 Jun 2006 at 7:02, Brian Blais wrote:

> Greg Ewing wrote:
> > Brian Blais wrote:
> >> I have found a very similar problem trying to replace a method using a 
> >> function defined in pyrex.
> > 
> > 
> > What *should* work is to define the method inside a
> > class in Pyrex (plain class, not extension type) and
> > extract it out of the class's __dict__. That's because
> > Pyrex pre-wraps a function defined in a class in an
> > unbound method object before putting it in the class.
> > 
> 
> So I tried:
> 
> #---------------------------------------------------------------------------------
> 
> #module_pyrex.pyx
> 
> class update_funcs:
> 
>      def pyrex_update_within_class(self,val):
>          print "pyrex module within class",val
> 
> 
> #---------------------------------------------------------------------------------
> 
> #(adding to test_replace_method.py)
> 
> This.update4=module_pyrex.update_funcs.__dict__['pyrex_update_within_class']
> 
> t.update4('pyrex within class') # doesn't work
> 
> #---------------------------------------------------------------------------------
> 
> and get:
> 
> TypeError: unbound method pyrex_update_within_class() must be called with 
> update_funcs instance as first argument (got str instance instead)
> 
> 
> did I do this wrong?

Nothing. Python's method type is just too specialized to work as Greg 
suggested. You will have to provide your own method descriptor. This 
works:

#--------------------------------------------------------------------

#module_pyrex.pyx

cdef extern from "python.h":
    object PyMethod_New(object func, object self, object cls)

# Yes, this has to be an extension type in Pyrex.
cdef class InstanceMethod:
    cdef object fn
    def __init__(self, fn):
        self.fn = fn
    def __get__(self, instance, owner):
        return PyMethod_New(self.fn, instance, owner)

def pyrex_update_within_class(self,val):
     print "pyrex module within class",val
pyrex_update_within_class = InstanceMethod(pyrex_update_within_class)

#--------------------------------------------------------------------

#(Make this replacement in main py module of original posting)

This.update3=module_pyrex.pyrex_update_within_class

#--------------------------------------------------------------------

InstanceMethod is minimal. Additions may be to make the fn attribute 
readable and a __call__ method that calls fn directly.

Lenard Lindstrom
<len-l at telus.net>





More information about the Python-list mailing list