views:

196

answers:

1

I would like to use the C implementation of a class method (generated from Cython) if it is present, or use its Python equivalent if the C extension is not present. I first tried this:

class A(object):
    try:
        import c_ext
        method = c_ext.optimized_method
    except ImportError:
        def method(self):
            return "foo"

Where optimized_method is a function defined in a Cython module:

def optimized_method(self):
    return "fasterfoo"

But this doesn't work:

>>> A().method()
exceptions.TypeError: optimized_method() takes exactly one argument (0 given)

The only way I found to make this work is:

class A(object):
    def method(self):
        try:
            import c_ext
            return c_ext.optimized_method(self)
        except ImportError:
            pass
        return "foo"

But checking for the module's presence at each function call seems quite suboptimal... Why isn't my first approach working ?

[edit] : added Cython module's contents

+2  A: 

Ok I just found the answer...

The problem comes from the way Cython wraps the functions it exports: every method is unbound regardless from where it is referenced.

The solution is to explicitly declare a bound method:

class A(object):
    def method(self):
        return "foo"

try:
    import c_ext
    import types
    A.method = types.MethodType(c_ext.optimized_method, None, A)
except ImportError:
    pass
Luper Rouch