[Cython] Speedup module-level lookup
Vitja Makarov
vitja.makarov at gmail.com
Sat Jan 21 09:35:44 CET 2012
2012/1/21 Stefan Behnel <stefan_ml at behnel.de>:
> Chris Colbert, 19.01.2012 09:18:
>> If it doesn't pass PyDict_CheckExact you won't be able to use it as the
>> globals to eval or exec.
>
> What makes you say that? I tried and it worked for me, all the way back to
> Python 2.4:
>
> --------------------
> Python 2.4.6 (#2, Jan 21 2010, 23:45:25)
> [GCC 4.4.1] on linux2
> Type "help", "copyright", "credits" or "license" for more information.
>>>> class MyDict(dict): pass
>>>> eval('1+1', MyDict())
> 2
>>>> exec '1+1' in MyDict()
>>>>
> --------------------
>
> I only see a couple of calls to PyDict_CheckExact() in CPython's sources
> and they usually seem to be related to special casing for performance
> reasons. Nothing that should impact a module's globals.
>
> Besides, Cython controls its own language usages of eval and exec.
>
Cool!
It seems that python internally uses PyObject_GetItem() for module
level lookups and not PyDict_GetItem().
Btw we use __Pyx_GetName() that calls PyObject_GetAttr() that isn't
exactly the same for module lookups:
# Works in Cython and doesn't work in Python
print __class__
So we can override __getitem__() and __setitem__():
class MyDict(dict):
def __init__(self):
self._dict = {}
def __getitem__(self, key):
print '__getitem__', key
return self._dict[key]
def __setitem__(self, key, value):
print '__setitem__', key, value
self._dict[key] = value
def __getattr__(self, key):
print '__getattr__'
d = MyDict()
exec('x = 1; print x', d)
eval('x', d)
$ python foo.py
__setitem__ x 1
__getitem__ x
1
__getitem__ x
So we can make globals() return special dict with custom
__setitem__()/__getitem__(). But it seems that we'll have to override
many dict's standard methods like values(), update() and so on. That
would be hard.
--
vitja.
More information about the cython-devel
mailing list