]> granicus.if.org Git - python/commitdiff
Make new classes dynamic by default.
authorGuido van Rossum <guido@python.org>
Thu, 4 Oct 2001 19:46:06 +0000 (19:46 +0000)
committerGuido van Rossum <guido@python.org>
Thu, 4 Oct 2001 19:46:06 +0000 (19:46 +0000)
Misc/NEWS
Objects/typeobject.c
PLAN.txt

index 1d437d09874a0994fc5098078e0034da8d8a7eed..726cc050a33b054ad8d65a759ec5cd320a7c9a94 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -4,6 +4,16 @@ Release date: 28-Sep-2100
 
 Type/class unification and new-style classes
 
+- New-style classes are now dynamic by default.  Previous, they were
+  static (meaning class attributes could not be assigned to) and
+  dynamic classes had to be requested by adding __dynamic__ = 1 to the
+  body of the class or to the module.  Static classes are faster than
+  dynamic classes, but dynamic classes are now at most 50% slower than
+  static classes; previously, they could be up to 10x slower.  (This
+  was accomplished by making dynamic classes faster, not by making
+  static classes slower. :-)  Note that according to one benchmark,
+  static classes are about the same speed as classic classes.
+
 - C.__doc__ now works as expected for new-style classes (in 2.2a4 it
   always returned None, even when there was a class docstring).
 
index fae159c26e021ffe3ec2a3a8168e303d08f0b88f..e4f07e534e31839d82148a17927bfcf471d10cac 100644 (file)
@@ -759,9 +759,7 @@ type_new(PyTypeObject *metatype, PyObject *args, PyObject *kwds)
           1) in the class dict
           2) in the module dict (globals)
           The first variable that is an int >= 0 is used.
-          Otherwise, a default is calculated from the base classes:
-          if any base class is dynamic, this class is dynamic; otherwise
-          it is static. */
+          Otherwise, the default is dynamic. */
        dynamic = -1; /* Not yet determined */
        /* Look in the class */
        tmp = PyDict_GetItemString(dict, "__dynamic__");
@@ -783,19 +781,9 @@ type_new(PyTypeObject *metatype, PyObject *args, PyObject *kwds)
                }
        }
        if (dynamic < 0) {
-               /* Make a new class dynamic if any of its bases is
-                  dynamic.  This is not always the same as inheriting
-                  the __dynamic__ class attribute! */
-               dynamic = 0;
-               for (i = 0; i < nbases; i++) {
-                       tmptype = (PyTypeObject *)
-                               PyTuple_GET_ITEM(bases, i);
-                       if (tmptype->tp_flags &
-                           Py_TPFLAGS_DYNAMICTYPE) {
-                               dynamic = 1;
-                               break;
-                       }
-               }
+               /* Default to dynamic */
+               dynamic = 1;
+
        }
 
        /* Check for a __slots__ sequence variable in dict, and count it */
index c88511c5b6a236d2bbc53c87c9fa1fe97e60913e..9e0fc67792a7907c20f6330486a7d68881dcad3c 100644 (file)
--- a/PLAN.txt
+++ b/PLAN.txt
@@ -4,21 +4,18 @@ Project: core implementation
 Still to do
 -----------
 
-Make __dynamic__ the default (this requires more performance work --
-one particular test, test_descr.inherits(), is about 10x slower when
-__dynamic__ is 1. :-(  There are two ways to go about the performance
-work:
+More performance work -- one particular test, test_descr.inherits(),
+is still about 50% slower with dynamic classes. :-(  The approach of
+choice would be:
 
- a) Add shortcuts to the slot_tp_XXX to recognize a PyWrapperDescr
-    with the correct wrap_tp_XXX function.
-
- b) Add a list or dict of weak refs to derived classes to each dynamic
+    Add a list of weak refs to derived classes to each dynamic
     class, and trap setattr+delattr on the base class so that they
     update the tp_XXX slot in each derived class when the base class
     __XXX__ gets set or deleted.  More work, but more gain (zero waste
-    in slot_tp_XXX when __XXX__ is not overridden).
+    in slot_tp_XXX when __XXX__ is not overridden).  This is currently
+    awaiting Fred turning the weak ref API into a standard object API.
 
-Add __del__ handlers.
+Add __del__ handlers?
 
 Allow assignment to __bases__ and __dict__?
 
@@ -39,6 +36,9 @@ implemented.
 Done (mostly)
 -------------
 
+Make __dynamic__ the default.  *** done (but more performance work
+needs to be done). ***
+
 Treat all binary operators the same way as I just did for rich
 comparison: in a <op> b, if type(a) is not type(b) and isinstance(b,
 type(a)), try b.__rop__(a) before trying a.__op__(b).  *** Done. ***