扩展Python的namedtuple:如何避免子类化的成本?

时间:2017-02-12 22:04:11

标签: python performance

我尝试将以下功能添加到Python collections.namedtuple

Lazy = namedtupleforthelazytm('Lazy', ('A', 'B'))
inst = Lazy(1, 2)
# namedtuple has this:
inst[0]
inst.A
# I want this:
SV = 'A'
inst[SV]

以下代码似乎只能实现

import collections

def namedtupleforthelazytm(classname, fieldnames):
    class lazy(collections.namedtuple(classname + '_wrapped', fieldnames)):
        __slots__ = ()
        def __getitem__(self, key):
            if key in self._fields:
                return super().__getattribute__(key)
            return super().__getitem__(key)
    lazy.__name__ = classname
    return lazy

然而,所造成的性能损失非常严重:

>>> from timeit import timeit
>>> from collections import namedtuple
>>> from nmdtpl import namedtupleforthelazytm
>>> 
>>> def stress(o):
...     for i in range(100000):
...         x = o[0]
...         x = o[1]
...         x = o.a
...         x = o.b
...
>>> orig = namedtuple('O', ('a', 'b'))(1, 2)
>>> subc = namedtupleforthelazytm('S', ('a', 'b'))(1, 2)
>>> 
>>> timeit('f(a)', number=10, globals={'f':stress, 'a':orig})
0.13294775993563235
>>> timeit('f(a)', number=10, globals={'f':stress, 'a':subc})
2.1330132230650634

我的问题是:有没有办法让所需功能更便宜(不一定从namedtuple开始)?

澄清:

namedtuple给我的美妙之处在于,与使用元组相比,它使代码更具可读性,同时避免了完整映射的成本。 我可以使用getattr(inst, SV),但这样做会破坏目的(可读性) - 如果你发现一个单一的太易于阅读以保证任何行动,那就认为是嵌套结构。

0 个答案:

没有答案