Author zseil
Recipients georg.brandl, rhettinger, terry.reedy, zseil
Date 2008-11-17.12:22:46
SpamBayes Score 0.0
Marked as misclassified No
Message-id <1226924655.56.0.446118247885.issue1694663@psf.upfronthosting.co.za>
In-reply-to
Content
Hi Raymond,

The signature matters because the current code in update_one_slot()
forgets to set the use_generic flag when slots have different wrappers.
This causes that the slot from the base class is left in the new type.
Slots have different wrappers when their signature differs.

I also found an old patch for this issue that fixes a few more corner
cases, but I can't remember if it is finished and it doesn't apply to
current trunk. I'll try to fix that soon, but here is the original
message and patch:

"""
Here is a new version of the patch.  It fixes another bug and
restores the optimization that was lost when dict.__getitem__
and list.__getitem__ became methods with a METH_COEXIST flag.

The bug that this patch fixes shows when a type has the wrong
__new__ method:

>>> class C(object):
...     __new__ = int.__new__
...
>>> C()            # should raise a TypeError, but doesn't
>>> C.__new__(C)   # raises a TypeError, as expected

This means that Guido should buy me a beer :).

Adding __getitem__ to dict's and list's methods slowed down the
corresponding operation for subclasses that don't overwrite
__getitem__.  update_one_slot() installs a generic wrapper when
a __special__ method is not a WrapperDescriptor.  As a consequence,
this code is slower:

>>> class MyList(list):
...     pass
...
>>> L = MyList([0])
>>> L[0]           # currently slower than without METH_COEXIST

set.__contains__ and dict.__contains__ have the same problem.
I'll attach a timeit script that shows the difference.

The basic idea of this patch is that when all of the __special__
methods for a particular slot are inherited from the same base,
we can safely use that base's slot for the subtype.  The patch
compares __special__ methods by identity, which eliminates all
of the problems listed in this bug report.  For more details,
see the comments in the patch.

The patch contains only the tests for the bugs reported here;
the old behavior is already thoroughly tested in test_descr's
dynamics(), overloading(), subclasspropagation() and other
functions.

The patch introduces a slight incompatibility with Python 2.4 and
2.5; code that calls PySequence_GetItem(dict_subclass, index) for
dict subclasses can now fail, because tp_as_sequence->sq_item gets
filled only if the subclass overwrites the __getitem__ method.

Here are the results of running the script on a trunk build:

 list test: 0.585701534692
 dict test: 0.562311969817
  set test: 0.468992008761
class test: 0.235781083909

and results of running the script with this patch applied:

 list test: 0.167487487935
 dict test: 0.149341885631
  set test: 0.153591029027
class test: 0.211393347479
"""
History
Date User Action Args
2008-11-17 12:24:15zseilsetrecipients: + zseil, georg.brandl, rhettinger, terry.reedy
2008-11-17 12:24:15zseilsetmessageid: <1226924655.56.0.446118247885.issue1694663@psf.upfronthosting.co.za>
2008-11-17 12:22:54zseillinkissue1694663 messages
2008-11-17 12:22:51zseilcreate