从其他模块访问 python namedtuple _fields

Accessing python namedtuple _fields from other modules

我希望能够从另一个模块中获取 namedtuple 的 _fields 成员的长度。但是,它被标记为受保护。

我的解决方法如下:

MyTuple = namedtuple(
    'MyTuple', 
    'a b'
)
"""MyTuple description

Attributes:
    a (float): A descrip
    b (float): B descrip
"""
NUM_MY_TUPLE_FIELDS = len(MyTuple._fields)

然后我从外部模块导入NUM_MY_TUPLE_FIELDS。

我试图找到一种方法来使 class 的功能成为一部分,例如使用 __len__ 方法扩展 namedtuple。是否有更 pythonic 的方法从外部模块获取 namedtuple 中的字段数?

已更新以显示 autodoc 注释。在 PyCharm 中可以看到受保护的警告。最初,在外部模块中我只是简单地导入了 MyTuple,然后使用:

x = len(MyTuple._fields)

我尝试了以下建议并认为它会起作用,但我得到以下信息:TypeError:类型 'type' 的对象没有 len()。

class MyTuple(typing.MyTuple):
    a: float
    b: float
    """MyTuple doc

    Attributes:
        a (float): A doc
        b (float): B doc
    """
    def __len__(self) -> int:
        return len(self._fields)

fmt_str = f"<L {len(MyTuple)}f"   # for struct.pack usage
print(fmt_str)

你可以使用继承:

class MyTuple(namedtuple('MyTuple', 'a b c d e f')): 
    """MyTuple description

    Attributes:
       a (float): A description 
       ...
    """
    @property
    def fields(self): 
        # _fields is a class level attribute and available via
        # MyTuple._fields from external modules
        return self._fields

    def __len__(self): 
        # your implementation if you need it
        return len(self._fields)

如果您使用 python 3.5+

,则使用 typing.NamedTuple
class MyTuple(typing.NamedTuple): 
   a: int
   # other fields 

一种方法是使用 inspect.signature 并计算 __new__ 方法需要多少个参数:

import inspect
n_fields = len(inspect.signature(NTClass).parameters)

这是有效的,因为 typing.NamedTuple 不允许覆盖 __new__ 方法,并且由于它的实现方式不太可能改变:

>>> import inspect
>>> from typing import NamedTuple
>>> class NTClass(NamedTuple):
...  x: int
...  y: float
...
>>> len(inspect.signature(NTClass).parameters)
2

它也适用于旧的 collections.namedtuple:

>>> from collections import namedtuple
>>> NTClass = namedtuple("NTClass", "x y")
>>> len(inspect.signature(NTClass).parameters)
2