summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTim Peters <tim.peters@gmail.com>2001-05-11 21:51:48 (GMT)
committerTim Peters <tim.peters@gmail.com>2001-05-11 21:51:48 (GMT)
commitd85e102337725554a43027fe90e54dd886f4ec9a (patch)
treed0bc76afbeace03a71537ba84504c2eea891c171
parent564a6cc8cae4cd9461c01ac4c7a14915744bcc1e (diff)
downloadcpython-d85e102337725554a43027fe90e54dd886f4ec9a.zip
cpython-d85e102337725554a43027fe90e54dd886f4ec9a.tar.gz
cpython-d85e102337725554a43027fe90e54dd886f4ec9a.tar.bz2
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.
-rw-r--r--Misc/NEWS3
-rw-r--r--Objects/moduleobject.c69
2 files changed, 38 insertions, 34 deletions
diff --git a/Misc/NEWS b/Misc/NEWS
index 8b4021f..b485959 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -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 ==.
diff --git a/Objects/moduleobject.c b/Objects/moduleobject.c
index f9c9228..6628fe9 100644
--- a/Objects/moduleobject.c
+++ b/Objects/moduleobject.c
@@ -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 */
};