[Python-Dev] Skiping searching throw dictionaries of mro() members.

Sokolov Yura falcon at intercable.ru
Wed Sep 14 19:12:36 CEST 2005

Excuse my english.
I have a complex Idea. It can be not worth, but just look at.
It touches the classes and inheritance.
Base point:
We change classes not too often. But every look at a member leads to 
search throw
a __dict__ of  all bases in ierarhy till member found. We could cache 
this search in class.__dict__ itself and check only bases versions.
Lets see:
we have some classes:
class a:
....def meth_a(self):
class b:
....def meth_b(self):
class c(a,b):
Every class has mro.
[<class '__main__.c'>, <class '__main__.a'>, <class '__main__.b'>, <type 
if we call methon from a base class, we look at c.__dict__ and at dict 
of every inherited class till found the method itself.
so c.meth_a() leads to search throw c.__dict__ and a.__dict__
c.meth_b() leads to search throw c.__dict__ , a.__dict__ and b.__dict__

We could cash looks by this way:
Store with a class its version. Every time after creation when we change 
a class
(add,remove or chage class member, including __base__, __bases__ and mro) ,
we increase the version number. Lets call it VERSION
Also store a tuple MRO_VERSION=tuple(base.VERSION for base in self.mro()).
It changes, when  we  touches __base__, __bases__ or self.mro)
Store with every class member a tuple : MEMBER_VERSION=(<self.mro 
version>,<number in mro>)
When we add  member to (or change member of) class __dict__ directly,
we store in this tuple (MRO_VERSION,class.mro().index(class)).

When we search a class member:
 and have not found it in class.__dict__, we search it throw mro() by a 
classic way.
If we've found it (in a class _BASE_), we store it in class.__dict__ 
with a tuple
MEMBER_VERSION=(MRO_VERSION, class.mro().index(_BASE_)).
Also we check all of seen base.VERSION to match their cached in 
MRO_VERSION values. If some is not match,
we should update MRO_VERSION (berfore storing founded member in a 
class.__dict__) and adjust VERSION.
If it was not found, we could store a (MRO_VERSION, 
class.mro().index(class)) with an internal value NotFound
 or do not store anything, and report that we have not found anything 
(so we search in an object itself).
When we've found a class member in class.__dict__ we check versions
if MEMBER_VERSION[0]==class.MRO_VERSION (the same object)
       then we just compare MRO_VERSION[i]==class.mro()[i].VERSION for i 
in range(MEMBER_VERSION[1]+1)
          and not search throw mro()[i].__dict__ what we are doing now.
          If all versions concur, we return found member
              (or, if we've found previously stored NotFound, we report 
that we have not found anything)
       if version of MRO_VERSION[j]!=class.mro()[j].VERSION and 
class!=class.mro()[j] (here can be a bug, one must think about it more)
           then we revert to a) point, but search throw [base.__dict__ 
for base in class.mro()[j:]], (and, of cause, update MRO_VERSION)
if  MEMBER_VERSION[0]!=class.MRO_VERSION, we reverts to a) point.

That's all.
PS. We can subclass module from a __builtin__, so we leave one dict lookup.

More information about the Python-Dev mailing list