子类化名为tuple的集合

2024-10-05 13:13:46 发布

您现在位置:Python中文网/ 问答频道 /正文

Python的namedtuple作为一个轻量级的、不可变的数据类非常有用。我喜欢将它们用于记账参数,而不是字典。当需要更多功能时,例如简单的docstring或默认值,您可以轻松地将namedtuple重构为类。但是,我见过从namedtuple继承的类。它们获得了哪些功能,失去了哪些性能?例如,我会将其实现为

from collections import namedtuple

class Pokemon(namedtuple('Pokemon', 'name type level')):
    """
    Attributes
    ----------
    name : str
        What do you call your Pokemon?
    type : str
        grass, rock, electric, etc.
    level : int
        Experience level [0, 100]
    """
     __slots__ = ()

唯一的目的是能够干净地记录属性,__slots__用于防止创建__dict__(保持namedtuples的轻量级性质)

有没有更好的建议使用轻量级数据类来记录参数?注意,我使用的是Python 2.7


Tags: 数据name功能参数字典type记录namedtuple
1条回答
网友
1楼 · 发布于 2024-10-05 13:13:46

新更新:

在Python3.6+中,可以使用新的类型化语法并创建typing.NamedTuple。新语法支持所有常见的python类创建功能(DocString、多重继承、默认参数、方法等从3.6.1开始提供):

import typing

class Pokemon(MyMixin, typing.NamedTuple):
    """
    Attributes
         
    name : str
        What do you call your Pokemon?
    type : str
        grass, rock, electric, etc.
    level : int
        Experience level [0, 100]
    """
    name: str
    type: str
    level: int = 0 # 3.6.1 required for default args

    def method(self):
        # method work

此版本创建的类对象大部分与原始collections.namedtupleexcept for a few details等效

您还可以使用与旧命名元组相同的语法:

Pokemon = typing.NamedTuple('Pokemon', [('name', str), ('type', str), ('level', int)])

原始答案


简短回答:no, unless you are using Python < 3.5

P3 docs似乎相当清楚地暗示,除非需要添加计算字段(即描述符),否则子类化namedtuple不被认为是规范方法。这是因为您可以直接更新docstring(从3.5开始,它们现在是可写的!)

Subclassing is not useful for adding new, stored fields. Instead, simply create a new named tuple type from the _fields attribute...

Docstrings can be customized by making direct assignments to the __doc__ fields...

更新:

现在,在最新版本的Python中,轻量级数据类还有一些其他令人信服的可能性

一个是^{} (Python 3.3 and later)。它的结构不像namedtuple,但结构并不总是必要的

关于SimpleNamespace需要注意的一点是:默认情况下,实例化类时需要显式指定字段名。不过,通过调用super().__init__可以相当容易地实现这一点:

from types import SimpleNamespace

class Pokemon(SimpleNamespace):
    """
    Attributes
         
    name : str
        What do you call your Pokemon?
    type : str
        grass, rock, electric, etc.
    level : int
        Experience level [0, 100]
    """
    __slots__ = ("name", "type", "level")
    # note that use of __init__ is optional
    def __init__(self, name, type, level):
        super().__init__(name=name, type=type, level=level)

另一个有趣的选择是{a6}(另见{a7}):

from dataclasses import dataclass

@dataclass
class Pokemon:
    __slots__ = ("name", "type", "level")
    name: str  # What do you call your Pokemon?
    type: str  # grass, rock, electric, etc.
    level: int = 0  # Experience level [0, 100]

请注意,这两个建议在默认情况下都是可变的,并且其中任何一个都不需要__slots__

相关问题 更多 >

    热门问题