[Python-Dev] other "magic strings" issues

Alex Martelli aleaxit at yahoo.com
Sun Nov 9 05:43:32 EST 2003


On Sunday 09 November 2003 01:28, Martin v. Löwis wrote:
> Alex Martelli wrote:
> > [[ I meant -- but didn't say out loud!-) -- "without changing the
> > current bytecode-level logic".  The change I proposed and experimented
> > with for strings' is... methods is localized to stringobject.c and
> > requires changing nothing except the details of string objects'
> > implementation ]]
>
> Then I probably don't understand what you are suggesting. What would
> LOAD_ATTR do if the object is a string, the attribute is "isdigit", and
> you were allowed to assume that the result won't depend on factors that
> may change over time?

The LOAD_ATTR attribute, using exactly the machinery it uses today,
gets to PyString_Type's tp_getattro slot, which is unchanged:
	PyObject_GenericGetAttr,		/* tp_getattro */

Only one slot in PyString_Type is changed at all:
	string_getsets,				/* tp_getset */

and it's changed from being 0 as it is now to pointing to:

static PyGetSetDef string_getsets[] = {
	{"isdigit", (getter)string_isdigit_getter, 0, isdigit_getter__doc__},
        /* other getsets snipped */
	{0}
};

string_isdigit_getter is quite similar to today's string_isdigit *EXCEPT*
that instead of returning True or False (via PyBool_FromLong(1) etc)
it returns one of two nullary callables which will always return True or
respectively False when called:

static PyObject * _isdigit_return_true = 0;
static PyObject * _isdigit_return_false = 0;
static PyObject * _isdigit_true_returner(PyObject* ignore_self)
{
	Py_RETURN_TRUE;
}
static PyObject * _isdigit_false_returner(PyObject* ignore_self)
{
	Py_RETURN_FALSE;
}
static PyMethodDef _str_bool_returners[] = {
	{"isdigit", (PyCFunction)_isdigit_false_returner, METH_NOARGS},
	{"isdigit", (PyCFunction)_isdigit_true_returner, METH_NOARGS},
        /* other "bool returners" snipped */
	{0}
};
static PyObject*
_return_returner(PyObject** returner, PyMethodDef *returner_method_def)
{
    if(!*returner)
        *returner = PyCFunction_New(returner_method_def, 0);
    Py_INCREF(*returner);
    return *returner;
}

so string_isdigit_getter uses
    return _return_returner(&_isdigit_return_true, _str_bool_returners+1);
where string_isdigit would instead use
    return PyBool_FromLong(1);

That's all there is to my proposal (we'd have another pair of 'bool 
returners' for isspace -- I think there are no other is... methods of 
strings suitable for this, given locale dependency of letter/upper/lower 
concepts) -- just a simple way to exploit descriptors to avoid creating
bound-method objects -- with a speedup of 30% compared with the
current implementations of isdigit and isspace (but the `in` operator is
jet another 30% faster in both cases).

Your proposal is vastly more ambitious and interesting, it seems to me.


Alex




More information about the Python-Dev mailing list