diff options
author | Raymond Hettinger <python@rcn.com> | 2004-03-18 08:38:00 (GMT) |
---|---|---|
committer | Raymond Hettinger <python@rcn.com> | 2004-03-18 08:38:00 (GMT) |
commit | 0ce6dc85300050356dfa127d741e80fdc9ad987a (patch) | |
tree | c91e503b59aaf8079758ae1586c78b9c26d51afa /Objects | |
parent | 0e5e6c70e6949bb82c54e1da2cff1836523902c4 (diff) | |
download | cpython-0ce6dc85300050356dfa127d741e80fdc9ad987a.zip cpython-0ce6dc85300050356dfa127d741e80fdc9ad987a.tar.gz cpython-0ce6dc85300050356dfa127d741e80fdc9ad987a.tar.bz2 |
Make the new dictionary iterators transparent with respect to length.
This gives another 30% speedup for operations such as
map(func, d.iteritems()) or list(d.iteritems()) which can both take
advantage of length information when provided.
Diffstat (limited to 'Objects')
-rw-r--r-- | Objects/dictobject.c | 24 |
1 files changed, 20 insertions, 4 deletions
diff --git a/Objects/dictobject.c b/Objects/dictobject.c index 1be0f42..7afc576 100644 --- a/Objects/dictobject.c +++ b/Objects/dictobject.c @@ -2013,6 +2013,7 @@ typedef struct { int di_used; int di_pos; PyObject* di_result; /* reusable result tuple for iteritems */ + long len; } dictiterobject; static PyObject * @@ -2026,6 +2027,7 @@ dictiter_new(dictobject *dict, PyTypeObject *itertype) di->di_dict = dict; di->di_used = dict->ma_used; di->di_pos = 0; + di->len = dict->ma_used; if (itertype == &PyDictIterItem_Type) { di->di_result = PyTuple_Pack(2, Py_None, Py_None); if (di->di_result == NULL) { @@ -2046,6 +2048,17 @@ dictiter_dealloc(dictiterobject *di) PyObject_Del(di); } +static int +dictiter_len(dictiterobject *di) +{ + return di->len; +} + +static PySequenceMethods dictiter_as_sequence = { + (inquiry)dictiter_len, /* sq_length */ + 0, /* sq_concat */ +}; + static PyObject *dictiter_iternextkey(dictiterobject *di) { PyObject *key; @@ -2074,6 +2087,7 @@ static PyObject *dictiter_iternextkey(dictiterobject *di) di->di_pos = i+1; if (i > mask) goto fail; + di->len--; key = ep[i].me_key; Py_INCREF(key); return key; @@ -2087,7 +2101,7 @@ fail: PyTypeObject PyDictIterKey_Type = { PyObject_HEAD_INIT(&PyType_Type) 0, /* ob_size */ - "dictionary-keyiterator", /* tp_name */ + "dictionary-keyiterator", /* tp_name */ sizeof(dictiterobject), /* tp_basicsize */ 0, /* tp_itemsize */ /* methods */ @@ -2098,7 +2112,7 @@ PyTypeObject PyDictIterKey_Type = { 0, /* tp_compare */ 0, /* tp_repr */ 0, /* tp_as_number */ - 0, /* tp_as_sequence */ + &dictiter_as_sequence, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ @@ -2144,6 +2158,7 @@ static PyObject *dictiter_iternextvalue(dictiterobject *di) di->di_pos = i+1; if (i > mask) goto fail; + di->len--; Py_INCREF(value); return value; @@ -2167,7 +2182,7 @@ PyTypeObject PyDictIterValue_Type = { 0, /* tp_compare */ 0, /* tp_repr */ 0, /* tp_as_number */ - 0, /* tp_as_sequence */ + &dictiter_as_sequence, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ @@ -2223,6 +2238,7 @@ static PyObject *dictiter_iternextitem(dictiterobject *di) if (result == NULL) return NULL; } + di->len--; key = ep[i].me_key; value = ep[i].me_value; Py_INCREF(key); @@ -2251,7 +2267,7 @@ PyTypeObject PyDictIterItem_Type = { 0, /* tp_compare */ 0, /* tp_repr */ 0, /* tp_as_number */ - 0, /* tp_as_sequence */ + &dictiter_as_sequence, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ |