From: Jeff A. <ja...@fa...> - 2018-12-12 09:34:49
|
We're discussing this in a couple of places already, but I wanted to ask here in case there are old hands subscribed who can shed any light. http://bugs.jython.org/issue2719 https://github.com/jythontools/jython/pull/126 PyObject.java contains some comments I've never understood and have had difficulty following (https://hg.python.org/jython/file/tip/src/org/python/core/PyObject.java#l218). It seems advice only relevant to those who extend PyObject, which is mostly us. And we certainly don't follow it in PyObjectDerived which contains the mechanism by which Python authors override __str__ and where toString delegates to __repr__. Generally, the plain dunder methods in Jython correspond to tp_* slots in CPython, and methods with a name like int___add__ to which they delegate are the implementation functions. Overriding __add__ to call int___add__ is equivalent to the action in CPython of placing a function pointer in a tp-slot. At present, __str__ and __repr__ do not follow this convention: __str__ defaults to __repr__ by this mechanism, as expected. However, we tell people not to override these methods, but to define the result of either by overriding Object.toString. No real clue there what to do if they should give different results. Moreover, we expose (the non-final) Java PyObject.__repr__ as Python object.__str__, and something we call object_toString as object.__repr__. The logic of this cross-wiring is not explained, except that there will be a stack overflow if you don't. But why is this the right way to solve that problem? To me the obvious pattern is something like: 1. __str__ calls final object___str__, which is exposed as object.__str__ . 2. object___str__ calls __repr__ 3. __repr__ calls final object___repr__, which is exposed as object.__repr__ . 4. toString calls __str__ and we discourage overriding it because that's what __str__ is for in Python objects. Then in PyObjectDerived we do not override toString, but as normal all slot functions do their look-up for exposed versions and toString continues to call __str__. I think this defuses the stack overflow in a natural way, but if it doesn't, we look for some other solution than the one we have now. I notice that in CPython, these slots are wrapped with a little more logic (e.g. https://github.com/python/cpython/blob/2.7/Objects/object.c#L453), whereas in Jython we tend to call __str__ and so on directly. This may also be part of the right solution for us: to be investigated. Jeff -- Jeff Allen |