Cython will not perform any magic here: it will just delegate the calls to PyDict_GetItemWithError
- basically the same thing the Python interpreter will do (but probably slightly faster).
However, an unicode-object (I assume we are speaking about Python3-strings) caches its hash-value (in PyUnicodeObject.hash
-member field), so this needs to be calculated only once - which makes sense because an unicode-object is immutable, that means the hash cannot change.
Here is the CPython code responsible for the hash calculation/caching:
#define _PyUnicode_HASH(op) \
(((PyASCIIObject *)(op))->hash)
...
static Py_hash_t
unicode_hash(PyObject *self)
{
...
// if hash already calculated, return cached value
if (_PyUnicode_HASH(self) != -1)
return _PyUnicode_HASH(self);
...
// else caclculate hash, cache value, return it
x = _Py_HashBytes(PyUnicode_DATA(self),
PyUnicode_GET_LENGTH(self) * PyUnicode_KIND(self));
_PyUnicode_HASH(self) = x;
return x;
}
So as you can see, there is no need for Cython to avoid the hash-recalculation - this optimization is already done by CPython.
By using Cython here, one could win up to 10-30% because it would eliminate the interpreter for this part of the code (see for example this SO-post) - not really much, but better than nothing.