bpo-32492: 1.6x speed up in namedtuple attribute access using C fast-path (#10495)

* bpo-32492: 2.5x speed up in namedtuple attribute access using C fast path

* Add News entry

* fixup! bpo-32492: 2.5x speed up in namedtuple attribute access using C fast path

* Check for tuple in the __get__ of the new descriptor and don't cache the descriptor itself

* Don't inherit from property. Implement GC methods to handle __doc__

* Add a test for the docstring substitution in descriptors

* Update NEWS entry to reflect time against 3.7 branch

* Simplify implementation with argument clinic, better error messages, only __new__

* Use positional-only parameters for the __new__

* Use PyTuple_GET_SIZE and PyTuple_GET_ITEM to tighter the implementation of tuplegetterdescr_get

* Implement __set__ to make tuplegetter a data descriptor

* Use Py_INCREF now that we inline PyTuple_GetItem

* Apply the valid_index() function, saving one test

* Move Py_None test out of the critical path.
This commit is contained in:
Pablo Galindo 2018-12-30 09:24:03 +00:00 committed by Raymond Hettinger
parent b0a6196ffd
commit 3f5fc70c62
5 changed files with 211 additions and 4 deletions

View file

@ -311,6 +311,11 @@ except ImportError:
### namedtuple
################################################################################
try:
from _collections import _tuplegetter
except ImportError:
_tuplegetter = lambda index, doc: property(_itemgetter(index), doc=doc)
_nt_itemgetters = {}
def namedtuple(typename, field_names, *, rename=False, defaults=None, module=None):
@ -454,12 +459,13 @@ def namedtuple(typename, field_names, *, rename=False, defaults=None, module=Non
cache = _nt_itemgetters
for index, name in enumerate(field_names):
try:
itemgetter_object, doc = cache[index]
doc = cache[index]
except KeyError:
itemgetter_object = _itemgetter(index)
doc = f'Alias for field number {index}'
cache[index] = itemgetter_object, doc
class_namespace[name] = property(itemgetter_object, doc=doc)
cache[index] = doc
tuplegetter_object = _tuplegetter(index, doc)
class_namespace[name] = tuplegetter_object
result = type(typename, (tuple,), class_namespace)