[pypy-svn] r8981 - pypy/dist/pypy/lib

pedronis at codespeak.net pedronis at codespeak.net
Tue Feb 8 12:20:14 CET 2005


Author: pedronis
Date: Tue Feb  8 12:20:14 2005
New Revision: 8981

Modified:
   pypy/dist/pypy/lib/_classobj.py
Log:
use hidden away slots in app-level implemented old-style classes to avoid abusing __dict__ to 
store __class__ __bases__ and __name__ special attributes .




Modified: pypy/dist/pypy/lib/_classobj.py
==============================================================================
--- pypy/dist/pypy/lib/_classobj.py	(original)
+++ pypy/dist/pypy/lib/_classobj.py	Tue Feb  8 12:20:14 2005
@@ -21,13 +21,22 @@
         v += 1
     return v & MASK
 
+# we use slots that we remove from type __dict__ for special attributes
+#
+# for classobj they are __bases__ and __name__ (classobj_bases_slot, classobj_name_slot)
+# for instance it's __class__ (instance_class_slot)
+
+
+# ____________________________________________________________
+# classobj def
+
 def type_err(arg, expected, v):
    return TypeError("argument %s must be %s, not %s" % (arg, expected, type(v).__name__))
 
 def set_name(cls, name):
     if not isinstance(name, str):
         raise TypeError, "__name__ must be a string object"
-    obj_setattr(cls, '__name__', name)
+    classobj_name_slot.__set__(cls, name)
 
 def set_bases(cls, bases):
     if not isinstance(bases, tuple):
@@ -35,14 +44,11 @@
     for b in bases:
         if not isinstance(b, classobj):
             raise TypeError, "__bases__ items must be classes"
-    obj_setattr(cls, '__bases__', bases)
+    classobj_bases_slot.__set__(cls, bases)
 
 def set_dict(cls, dic):
     if not isinstance(dic, dict):
         raise TypeError, "__dict__ must be a dictionary object"
-    # preserved __name__ and __bases__
-    dic['__name__'] = cls.__name__
-    dic['__bases__'] = cls.__bases__
     obj_setattr(cls, '__dict__', dic)
 
 def retrieve(obj, attr):
@@ -58,7 +64,7 @@
         v = retrieve(cls, attr)
         return v, cls
     except AttributeError:
-        for b in obj_getattribute(cls, '__bases__'):
+        for b in classobj_bases_slot.__get__(cls):
             v, found = lookup(b, attr)
             if found:
                 return v, found
@@ -95,6 +101,8 @@
 
 class classobj(object):
 
+    __slots__ = ('_name', '_bases', '__dict__')
+
     def __new__(subtype, name, bases, dic):
         if not isinstance(name, str):
             raise type_err('name', 'string', name)
@@ -135,8 +143,8 @@
         new_class = object.__new__(classobj)
 
         obj_setattr(new_class, '__dict__', dic)
-        obj_setattr(new_class, '__name__', name)
-        obj_setattr(new_class, '__bases__', bases)
+        classobj_name_slot.__set__(new_class, name)
+        classobj_bases_slot.__set__(new_class, bases)
 
         return new_class
 
@@ -160,11 +168,14 @@
     def __getattribute__(self, attr):
         if attr == '__dict__':
             return obj_getattribute(self, '__dict__')
+        if attr == '__name__':
+            return classobj_name_slot.__get__(self)
+        if attr == '__bases__':
+            return classobj_bases_slot.__get__(self)
+            
         v, found = lookup(self, attr)
         if not found:
             raise AttributeError, "class %s has no attribute %s" % (self.__name__, attr)
-        if attr in ('__name__', '__bases__'):
-            return v
 
         descr_get = mro_lookup(v, '__get__')
         if descr_get is None:
@@ -185,7 +196,7 @@
     def __call__(self, *args, **kwds):
         inst = object.__new__(instance)
         dic = inst.__dict__
-        dic['__class__'] = self
+        instance_class_slot.__set__(inst, self)
         init = instance_getattr1(inst,'__init__', False)
         if init:
             ret = init(*args, **kwds)
@@ -193,21 +204,25 @@
                 raise TypeError("__init__() should return None")
         return inst
 
-# first we use the object's dict for the instance dict.
-# with a little more effort, it should be possible
-# to provide a clean extra dict with no other attributes
-# in it.
+# capture _name, _bases slots for usage and then hide them!
+
+classobj_name_slot  = classobj._name
+classobj_bases_slot = classobj._bases
+
+del classobj._name, classobj._bases
+
+# ____________________________________________________________
+# instance def
 
 def instance_getattr1(inst, name, exc=True):
     if name == "__dict__":
         return obj_getattribute(inst, name)
     elif name == "__class__":
-        # for now, it lives in the instance dict
-        return retrieve(inst, name)
+        return instance_class_slot.__get__(inst)
     try:
         return retrieve(inst, name)
     except AttributeError:
-        cls = retrieve(inst, "__class__")
+        cls = instance_class_slot.__get__(inst)
         v, found = lookup(cls, name)
         if not found:
             if exc:
@@ -220,6 +235,9 @@
         return descr_get(v, inst, cls)
 
 class instance(object):
+
+    __slots__ = ('_class', '__dict__')
+    
     def __getattribute__(self, name):
         try:
             return instance_getattr1(self, name)
@@ -238,7 +256,7 @@
         elif not isinstance(dic, dict):
             raise TypeError("instance() second arg must be dictionary or None")
         inst = object.__new__(instance)
-        dic['__class__'] = klass
+        instance_class_slot.__set__(inst, klass)
         obj_setattr(inst, '__dict__', dic)
         return inst
 
@@ -246,14 +264,11 @@
         if name == '__dict__':
             if not isinstance(value, dict):
                 raise TypeError("__dict__ must be set to a dictionary")
-            # for now, we need to copy things, because we are using
-            # the __dict__for our class as well. This will vanish!
-            value['__class__'] = self.__class__
             obj_setattr(self, '__dict__', value)
         elif name == '__class__':
             if not isinstance(value, classobj):
                 raise TypeError("__class__ must be set to a class")
-            self.__dict__['__class__'] = value
+            instance_class_slot.__set__(inst, value)
         else:
             setattr = instance_getattr1(self, '__setattr__', exc=False)
             if setattr is not None:
@@ -530,5 +545,9 @@
                     return 0
                 raise TypeError,"__cmp__ must return int"
         return NotImplemented
+
+# capture _class slot for usage and then hide them!
+instance_class_slot = instance._class
+del instance._class
     
 del _compile, NiceCompile



More information about the Pypy-commit mailing list