Variant of patch #423262: Change module attribute get & set

Allow module getattr and setattr to exploit string interning, via the
previously null module object tp_getattro and tp_setattro slots.   Yields
a very nice speedup for things like random.random and os.path etc.
This commit is contained in:
Tim Peters 2001-05-11 21:51:48 +00:00
parent 564a6cc8ca
commit d85e102337
2 changed files with 38 additions and 34 deletions

View File

@ -44,6 +44,9 @@ Core
'x in y' and 'x not in y' (PySequence_Contains() in C API)
operator.countOf() (PySequence_Count() in C API)
- Accessing module attributes is significantly faster (for example,
random.random or os.path or yourPythonModule.yourAttribute).
- Comparing dictionary objects via == and != is faster, and now works even
if the keys and values don't support comparisons other than ==.

View File

@ -162,17 +162,18 @@ module_repr(PyModuleObject *m)
}
static PyObject *
module_getattr(PyModuleObject *m, char *name)
module_getattro(PyModuleObject *m, PyObject *name)
{
PyObject *res;
char* modname;
if (strcmp(name, "__dict__") == 0) {
char *sname = PyString_AsString(name);
if (sname[0] == '_' && strcmp(sname, "__dict__") == 0) {
Py_INCREF(m->md_dict);
return m->md_dict;
}
res = PyDict_GetItemString(m->md_dict, name);
res = PyDict_GetItem(m->md_dict, name);
if (res == NULL) {
modname = PyModule_GetName((PyObject *)m);
char *modname = PyModule_GetName((PyObject *)m);
if (modname == NULL) {
PyErr_Clear();
modname = "?";
@ -187,30 +188,30 @@ module_getattr(PyModuleObject *m, char *name)
}
static int
module_setattr(PyModuleObject *m, char *name, PyObject *v)
module_setattro(PyModuleObject *m, PyObject *name, PyObject *v)
{
char* modname;
if (name[0] == '_' && strcmp(name, "__dict__") == 0) {
char *sname = PyString_AsString(name);
if (sname[0] == '_' && strcmp(sname, "__dict__") == 0) {
PyErr_SetString(PyExc_TypeError,
"read-only special attribute");
return -1;
}
if (v == NULL) {
int rv = PyDict_DelItemString(m->md_dict, name);
int rv = PyDict_DelItem(m->md_dict, name);
if (rv < 0) {
modname = PyModule_GetName((PyObject *)m);
char *modname = PyModule_GetName((PyObject *)m);
if (modname == NULL) {
PyErr_Clear();
modname = "?";
}
PyErr_Format(PyExc_AttributeError,
"'%.50s' module has no attribute '%.400s'",
modname, name);
modname, sname);
}
return rv;
}
else
return PyDict_SetItemString(m->md_dict, name, v);
return PyDict_SetItem(m->md_dict, name, v);
}
/* We only need a traverse function, no clear function: If the module
@ -226,26 +227,26 @@ module_traverse(PyModuleObject *m, visitproc visit, void *arg)
PyTypeObject PyModule_Type = {
PyObject_HEAD_INIT(&PyType_Type)
0, /*ob_size*/
"module", /*tp_name*/
sizeof(PyModuleObject) + PyGC_HEAD_SIZE, /*tp_size*/
0, /*tp_itemsize*/
(destructor)module_dealloc, /*tp_dealloc*/
0, /*tp_print*/
(getattrfunc)module_getattr, /*tp_getattr*/
(setattrfunc)module_setattr, /*tp_setattr*/
0, /*tp_compare*/
(reprfunc)module_repr, /*tp_repr*/
0, /*tp_as_number*/
0, /*tp_as_sequence*/
0, /*tp_as_mapping*/
0, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
0, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_GC, /*tp_flags*/
0, /* tp_doc */
(traverseproc)module_traverse, /* tp_traverse */
0, /* ob_size */
"module", /* tp_name */
sizeof(PyModuleObject) + PyGC_HEAD_SIZE,/* tp_size */
0, /* tp_itemsize */
(destructor)module_dealloc, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_compare */
(reprfunc)module_repr, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
(getattrofunc)module_getattro, /* tp_getattro */
(setattrofunc)module_setattro, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_GC, /* tp_flags */
0, /* tp_doc */
(traverseproc)module_traverse, /* tp_traverse */
};