mirror of
https://github.com/python/cpython.git
synced 2025-01-19 06:54:52 +08:00
Make new classes dynamic by default.
This commit is contained in:
parent
ba001a0b67
commit
50fda3ba26
10
Misc/NEWS
10
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).
|
||||
|
||||
|
@ -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 */
|
||||
|
20
PLAN.txt
20
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. ***
|
||||
|
Loading…
Reference in New Issue
Block a user