子类化列表的 Pythonic 方式

Pythonic way of subclassing a list

这是我的一般问题space:

我有一个 byte/bit 协议与一个基于 I2C 的设备。

我有 "database" 个命令来完整描述所有位域类型和值以及枚举。

我有一个 class 来使用数据库和一个 i2c driver/transactor 以便我可以调用命令并获得响应。

MyProtocol = Protocol('database.xml',I2CDriver())
theStatus = MyProtocol.GET_STATUS()

为 GET_STATUS 命令创建正确的字节流,通过 i2c 发送它,returns 当前作为字节数组的响应。我可以让它漂亮地打印 GET_STATUS() 实现内部的响应,但我想将该行为移动到 return 对象,而不是命令中。

我希望我的 return 对象是 'smart':theStatus 需要 list/array 字节加上对其字段定义的引用。

我希望 theStatus 像 list/bytearray 一样工作,这样我就可以直接检查字节。我不在乎切片是不是字节列表或字节数组。一旦它们被切出,它们就只是字节。

我希望 'theStatus' 能够被打印 print(theStatus) 并让它漂亮地打印状态中的所有字段。一旦我确定了一个允许我访问字节和数据库的可行数据结构,我就很清楚如何实现这一点。

我想通过 theStatus.FIELDNAMEtheStatus['FIELDNAME']' 之类的字段名称检查 theStatus。同样的事情:一旦我有了一个以字节数组和数据库为成员的可行数据结构,我就可以做到这一点。

问题是我不知道 "right" 数据结构引起的问题最少。

关于最 pythonic 实现此目的的任何建议?我最初的想法是子 class list 并将字段定义添加为成员,但似乎 python 根本不喜欢这个想法。

组合似乎是下一个赌注,但让它表现得像一个合适的 list 似乎要完成它可能需要大量工作 'right'。

创建一个继承自 collections.UserList 的子类,这正是 https://docs.python.org/3/library/collections.html#collections.UserList

的用途

您真正想要的是实现一个新的 sequence type, one that is perhaps mutable. You can either create one from scratch by implementing the special methods needed to emulate container types, or you can use a suitable collections.abc collection ABC 作为基础。

后者可能是最简单的方法,因为 ABC 提供了许多方法的实现作为基础版本,这些方法依赖于您必须实现的一些抽象方法。

例如,(不可变的)Sequence ABC 只需要您提供 __getitem____len__ 的实现;基本 ABC 实现提供了其余部分:

from collections.abc import Sequence

class StatusBytes(Sequence):
    def __init__(self, statusbytes):
        self._bytes = statusbytes

    def __getitem__(self, idx_or_name):
        try:
            return self._bytes[idx_or_name]
        except IndexError:
            # assume it is a fieldname
            return FIELDNAMES[idx_or_name]

    def __len__(self):
        return len(self._bytes)

如果你真的需要一个完整的列表实现,包括支持丰富的比较(list_a <= list_b)、排序(list_a.sort())、复制[list_a.copy()]和乘法(list_a * 3),然后还有 collections.UserList() class。 class 继承自 collections.abc.MutableSequence,并添加了 list 在基本序列 ABC 上提供的额外功能。如果您不需要额外的功能,请坚持使用基础 ABC。

听起来您正在寻找 collections.UserList