Mel wrote: > rekkufa wrote: [ ... ] >> How to load >> data that specifies immutables that recursively reference >> themselves. > I can imagine a C function that might do it. [ ... ]
Here's something that works, in the sense of creating a tuple containing a self-reference. I don't know how dangerous it realliy is -- haven't tested for memory leaks or any other large-scale trouble. Also, I've only tested on Python 2.5.1 under Ubuntu Linux. Called as idiotuple.idiotuple (a_sequence, a_marker) it returns a tuple containing the items of a_sequence, except that instances of a_marker are replaced by references to the returned tuple. Eg.: import idiotuple class IdioMarker: "An object that I will never insert into a tuple." def showid (x): print id(x) for y in x: print ' ', id(y) showid (idiotuple.idiotuple ((1,2,3), IdioMarker)) showid (idiotuple.idiotuple ((1, IdioMarker, 3), IdioMarker)) The C code is: /* $Id$ */ #include <Python.h> /*=======================================================*/ static PyObject *idiotuple_idiotuple (PyObject *self, PyObject *args) // In Python, call with // sequence contents // object marker // returns // tuple containing contents, with instances of marker // replaced by borrowed self-references { PyObject *t = NULL; PyObject *contents, *marker, *x; Py_ssize_t i, n, z; if (!PyArg_ParseTuple (args, "OO", &contents, &marker)) return NULL; n = PySequence_Size (contents); if (n < 0) return NULL; t = PyTuple_New (n); // new tuple if (t == NULL) return NULL; for (i=0; i < n; ++i) { x = PySequence_GetItem (contents, i); // new reference if (x != marker) { z = PyTuple_SetItem (t, i, x); // steals the new reference to x if (z == -1) { goto fail; } } if (x == marker) { z = PyTuple_SetItem (t, i, t); // stolen reference to t // Dereference the marker. // The internal reference to the tuple is effectively 'borrowed'. // Only external references to the tuple are reflected in its reference count. Py_DECREF (x); // dereference the marker if (z == -1) { goto fail; } } } return t; fail: Py_DECREF (t); // arrange for the tuple to go away return NULL; } /* idiotuple_idiotuple */ /*=======================================================*/ static PyMethodDef IdioTupleMethods[] = { {"idiotuple", idiotuple_idiotuple, METH_VARARGS, "Create a possibly self-referential tuple."}, {NULL, NULL, (int)NULL, NULL} }; PyMODINIT_FUNC initidiotuple (void) { PyObject *module; module = Py_InitModule ("idiotuple", IdioTupleMethods); } Setup.py is # for use by distutils from distutils.core import setup, Extension module1 = Extension('idiotuple', sources = ['idiotuple.c']) setup (name = 'idiotuple', version = '1.0', description = 'Create a possibly self-referential tuple.', author = 'Mel Wilson', author_email = '[EMAIL PROTECTED]', ext_modules = [module1]) -- http://mail.python.org/mailman/listinfo/python-list