A function—whether defined with lambda
or def
—is not a method.
You can't just change its type; a method has more information in it than a function—it's bound to an object. That's how Python knows what to pass for the first (self
) parameter.
In your case, you're looking for an unbound method, which isn't bound to an object—but it's still bound to a class.
In normal cases (when you def
a method inside a class
definition, then create an instance of the class, then call a method on it), this happens automatically for you. (See How methods work for some details.) But when you're doing it all yourself, you need to create the bound method yourself.
As with any other type in Python, you do this by calling the type as a constructor. The problem is that "bound method" isn't accessible as a builtin type. That means you have to go to the types
module, which "defines names for some object types that are used by the standard Python interpreter". Like this:
bound = types.MethodType(func, my_obj, type(my_obj))
unbound = types.UnboundMethodType(func, None, my_type)
But notice that there's often no good reason to do this—you could just as easily cram the object into the closure. These callables will all do the same thing:
func = lambda self: self
bound = types.MethodType(func, my_obj, type(my_obj))
func2 = lambda: my_obj
func3 = lambda self: self
unbound = types.UnboundMethodType(func, None, my_type)
func3a = lambda: unbound(my_obj)
Two last thoughts:
If you understand about descriptors, the magic that makes @property
work and the magic that makes bound methods work will interfere with each other. I don't know if that's true with Enthough traits, but it might. So, the answer to your question could well turn out to be "you can't do that". Instead, you will have to create a Function
trait, and then a wrapper method that calls that trait explicitly.
If you use Python 3.x instead of 2.x, unbound methods go away (classes just use plain old functions), so a lot of the complexity you're hitting never arises.