From: Samuele P. <pe...@in...> - 2001-07-18 16:55:48
|
Note: I moved the discussion to jython-users, at least about this. This is about bound, unbound methods used from java side and a kind of strange interaction with name binding level redefinitions for classes in a PythonInterp. [Joseph Campbell] > Samuele, > Originally you had: > > import org.python.core.*; > import org.python.util.*; > > public class Test { > > public static void main(String[] args) { > PythonInterpreter interp = new PythonInterpreter(); > interp.exec("class A:\n def m(self,a,b):\n print a,b"); > PyClass A =(PyClass)interp.eval("A"); > PyInstance a = (PyInstance)A.__call__(); > PyObject m = A.__findattr__("m"); > > interp.exec("class A:\n def m(self,a,b):\n print b,a"); > PyClass A2 =(PyClass)interp.eval("A"); > PyInstance a2 = (PyInstance)A2.__call__(); > PyObject m2 = A2.__findattr__("m"); > > m2.__call__(a2,new PyInteger(1),new PyInteger(2)); > m.__call__(a,new PyInteger(1),new PyInteger(2)); > > } > } > > Which I agree works just fine... however if you modify to look like the > following: > import org.python.core.*; > import org.python.util.*; > > public class Test { > > public static void main(String[] args) { > PythonInterpreter interp = new PythonInterpreter(); > interp.exec("class A:\n def m(self,a,b):\n print a,b"); > interp.exec("class B(A):\n def n(self,a,b):\n print a,b"); > > PyClass class =(PyClass)interp.eval("B"); for my compiler to accept this, I should change class to clazz. > PyInstance instance = (PyInstance)class.__call__(); > PyObject obj = instance.__findattr__("n"); Differently from me you are retrieving the method from the instance, so you get a bound method. > > // This call works here. > obj.__call__(instance,new PyInteger(1),new PyInteger(2)); This is the wrong way to spell the call to a bound method, no instance needed. See later. > > interp.exec("class A:\n def m(self,a,b):\n print a,b"); > interp.exec("class B(A):\n def n(self,a,b):\n print a,b"); > > // This call doesn't work here. > obj.__call__(instance,new PyInteger(1),new PyInteger(2)); > } > } > > You should get the Trace telling you you have to call the unbound method with > an instance first argument. No, after the class -> clazz change I get: Exception in thread "main" Traceback (innermost last): (no code object) at line 0 TypeError: n() too many arguments; expected 3 got 4 Making perfecly sense, OTOH both these versions work: import org.python.core.*; import org.python.util.*; public class Test { public static void main(String[] args) { PythonInterpreter interp = new PythonInterpreter(); interp.exec("class A:\n def m(self,a,b):\n print a,b"); interp.exec("class B(A):\n def n(self,a,b):\n print a,b"); PyClass clazz =(PyClass)interp.eval("B"); PyInstance instance = (PyInstance)clazz.__call__(); PyObject obj = instance.__findattr__("n"); System.out.println(obj); // This call works here. obj.__call__(new PyInteger(1),new PyInteger(2)); interp.exec("class A:\n def m(self,a,b):\n print a,b"); interp.exec("class B(A):\n def n(self,a,b):\n print a,b"); // This call doesn't work here. obj.__call__(new PyInteger(1),new PyInteger(2)); } } giving: <method B.n of B instance at 5316106> 1 2 1 2 And: import org.python.core.*; import org.python.util.*; public class Test { public static void main(String[] args) { PythonInterpreter interp = new PythonInterpreter(); interp.exec("class A:\n def m(self,a,b):\n print a,b"); interp.exec("class B(A):\n def n(self,a,b):\n print a,b"); PyClass clazz =(PyClass)interp.eval("B"); PyInstance instance = (PyInstance)clazz.__call__(); PyObject obj = clazz.__findattr__("n"); System.out.println(obj); // This call works here. obj.__call__(instance,new PyInteger(1),new PyInteger(2)); interp.exec("class A:\n def m(self,a,b):\n print a,b"); interp.exec("class B(A):\n def n(self,a,b):\n print a,b"); // This call doesn't work here. obj.__call__(instance,new PyInteger(1),new PyInteger(2)); } } giving: <unbound method B.n> 1 2 1 2 The problem you get is more easely triggered through calling a method retrieved from a new class on a old class version instance, or the other way around. Hope this helps. OTOH I still don't see why simply redefining name bindings in the interp namespace can cause the problem you report, methods do not refer to classes by name but through a ref to the class first-class object. I'm still missing an example causing your problem. regards, Samuele Pedroni. |