Why doesn't the namedtuple module use a metaclass to create nt class objects?

后端 未结 4 1777
野性不改
野性不改 2021-02-18 14:02

I spent some time investigating the collections.namedtuple module a few weeks ago. The module uses a factory function which populates the dynamic data (the name of the new

4条回答
  •  小鲜肉
    小鲜肉 (楼主)
    2021-02-18 14:40

    There is another reason that none of the other answers hit upon*.

    A class can only have 1 metaclass. One reason for this is the metaclass acts as the factory that creates the class. It isn't possible to mix factories together willy nilly. You must create either a "combinatory factory" that knows how to call the multiple factories in the correct order, or a "child factory" that knows about the "parent factory", and uses it correctly.

    If the namedtuple used its own metaclass, inheritance involving any other metaclass would break:

    >>> class M1(type): ...
    ...
    >>> class M2(type): ...
    ...
    >>> class C1(metaclass=M1): ...
    ...
    >>> class C2(metaclass=M2): ...
    ...
    >>> class C(C1, C2): ...
    ...
    Traceback (most recent call last):
      File "", line 1, in 
    TypeError: metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases
    

    Instead, if you wanted to have your own metaclass and inherit from a namedtuple class, you'd have to use some sort of so-called namedtuple_meta metaclass to do that:

    from namedtuple import namedtuple_meta  # pretending this exists
    
    class MyMeta(type): ...
    
    class MyMetaWithNT(namedtuple_meta, MyMeta): ...
    
    class C(metaclass=MyMetaWithNT): ...
    

    ..or just inherit the custom metaclass from namedtuple_meta directly:

    class MyMeta(namedtuple_meta): ...
    
    class C(metaclass=MyMeta): ...
    

    This looks easy at first, but writing your own mataclass that plays nicely with some (complicated) nt metaclass could be become problematic very quickly. This limitation would probably not come up all THAT often, but often enough that it would hinder the usage of namedtuple. So it is definitely an advantage to have all namedtuple classes be of the type type, and removing the complexity of a custom metaclass.


    * Raymond Hettinger's comment does hint at it:

    It is a key feature for named tuples that they are exactly equivalent to a hand-written class.

提交回复
热议问题