首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >为什么namedtuple模块不使用元类来创建nt类对象?

为什么namedtuple模块不使用元类来创建nt类对象?
EN

Stack Overflow用户
提问于 2015-01-28 12:17:25
回答 1查看 1.7K关注 0票数 23

几周前,我花了一些时间调查collections.namedtuple module。该模块使用工厂函数将动态数据(新namedtuple类的名称和类属性名称)填充到一个非常大的字符串中。然后,以字符串(表示代码)作为参数执行exec,并返回新类。

有没有人知道为什么要这样做,因为有一种特定的工具可以用来处理这种事情,即元类?我自己并没有尝试过这样做,但是似乎使用namedtuple元类就可以轻松地完成namedtuple模块中发生的所有事情,如下所示:

代码语言:javascript
复制
class namedtuple(type):

等等。

EN

回答 1

Stack Overflow用户

发布于 2016-06-24 18:04:15

这是另一种方法。

代码语言:javascript
复制
""" Subclass of tuple with named fields """
from operator import itemgetter
from inspect import signature

class MetaTuple(type):
    """ metaclass for NamedTuple """

    def __new__(mcs, name, bases, namespace):
        cls = type.__new__(mcs, name, bases, namespace)
        names = signature(cls._signature).parameters.keys()
        for i, key in enumerate(names):
            setattr(cls, key, property(itemgetter(i)))
        return cls

class NamedTuple(tuple, metaclass=MetaTuple):
    """ Subclass of tuple with named fields """

    @staticmethod
    def _signature():
        " Override in subclass "

    def __new__(cls, *args):
        new = super().__new__(cls, *args)
        if len(new) == len(signature(cls._signature).parameters):
            return new
        return new._signature(*new)

if __name__ == '__main__':
    class Point(NamedTuple):
        " Simple test "
        @staticmethod
        def _signature(x, y, z): # pylint: disable=arguments-differ
            " Three coordinates "
    print(Point((1, 2, 4)))

如果这种方法有任何优点的话,那就是它的简单性。如果没有NamedTuple.__new__,它会更简单,因为它只用于强制执行元素计数。否则,它允许在命名元素之外添加匿名元素,省略元素的主要效果是在按名称访问省略的元素时对省略的元素进行IndexError (只需做一些可以转换为AttributeError的工作)。错误的元素计数的错误消息有点奇怪,但它让人明白了这一点。我不希望这在Python2上起作用。

还有进一步复杂化的空间,比如__repr__方法。我不知道与其他实现相比性能如何(缓存签名长度可能会有所帮助),但与原生namedtuple实现相比,我更喜欢调用约定。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/28184531

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档