列表子类化的Pythonic方法 [英] Pythonic way of subclassing a list

查看:76
本文介绍了列表子类化的Pythonic方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是我的一般问题空间:

Here's my general problem space:

我有一个字节/位协议,且设备通过I2C。

I have a byte/bit protocol with a device over I2C.

我有一个命令的数据库来完全描述所有位字段的类型,值和枚举。

I've got a "database" of the commands to fully describe all the bitfields types and values and enumerations.

我有一个使用数据库的类,并且i2c驱动程序/事务器,这样我就可以调用命令并获取响应。

I have a class to consume the database and a i2c driver/transactor so that I can then call commands and get responses.

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

为GET_STATUS命令,通过i2c发送,并以字节数组的形式返回响应。我可以用它漂亮地在GET_STATUS()实现中打印响应,但是我想将该行为移回对象而不是在命令中返回。

creates the proper byte stream for the GET_STATUS command, sends it over the i2c and returns the response as a byte array currently. I can get it to pretty print the response inside of the GET_STATUS() implementation, but I want to move that behavior to return object, rather than in the command.

I希望我的返回对象是智能对象: theStatus 需要字节列表/数组以及对其字段定义的引用。

I want my return object to be 'smart': theStatus needs to have the list/array of bytes plus a reference to its field definitions.

我希望 thestatus 像列表/字节数组一样工作,因此我可以直接检查字节。我不在乎切片是否是字节列表或字节数组以外的其他内容。一旦将它们切出,它们就只是字节。

I want theStatus to act like an list/bytearray, so I can directly inspect the bytes. I don't care if slices are anything other than lists of bytes or bytearray. Once they've been sliced out they're just bytes.

我希望能够打印'theStatus' print(theStatus)并漂亮地打印状态中的所有字段。一旦我确定了一个可行的数据结构,该结构允许我访问字节和数据库,我对如何实现此目标感到很满意。

I want 'theStatus' to be able to be printed print(theStatus) and have it pretty print all the fields in the status. I'm comfortable on how to make this happen once I settle on a workable data structure that allows me to access the bytes and the data base.

我要检查 theStatus 的字段名称,例如 theStatus.FIELDNAME theStatus ['FIELDNAME']' 。同样的事情:一旦我有了一个以字节数组和数据库为成员的可行数据结构,我就可以实现这一目标。

I want to inspect theStatus by field name with something like theStatus.FIELDNAME or maybe theStatus['FIELDNAME']'. Same thing: once I have a workable data structure that has the byte array and database as members, I can make this happen.

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

The problem is I don't know the "right" data structure to cause the least amount of problems.

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

Any suggestions on the most pythonic way to accomplish this? My initial thought was to subclass list and add the field definitions as a member, but it seems like python doesn't like that idea at all.

组合似乎是下一个赌注,但要使其像一个正确的 list 一样起作用,可能要花很多时间才能做到

Composition seems like the next bet, but getting it to act like a proper list seems like that might be a bunch of work to get it 'right'.

推荐答案

您真正想要的是实现一个新的 序列类型,这可能是可变的。您可以通过实施仿真所需的特殊方法来从头创建一个容器类型,或者您可以使用合适的 collections.abc 集合ABC 作为基础。

What you really want is to implement a new 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 as a base.

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

The latter is probably the easiest path to take, as the ABCs provide implementations for many of the methods as base versions that rely on a few abstract methods you must implement.

例如,(不可变的)< a href = https://docs.python.org/3/library/collections.abc.html#collections.abc.Sequence rel = noreferrer> 序列 ABC 仅要求您提供 __ getitem __ __ len __ 的实现;基本的ABC实现将提供其余的信息:

For example, the (immutable) Sequence ABC only requires you to provide implementations for __getitem__ and __len__; the base ABC implementation provides the rest:

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()。此类从 collections.abc.MutableSequence 继承,并添加 list 在基本序列ABC上提供的额外功能。如果您不需要需要其他功能,请坚持使用基本ABC。

If you really need a full list implementation, including support for rich comparisons (list_a <= list_b), sorting (list_a.sort()), copying [list_a.copy()] and multiplication (list_a * 3), then there is also the collections.UserList() class. This class inherits from collections.abc.MutableSequence, and adds the extra functionality that list offers over the base sequence ABCs. If you don't need that extra functionality, stick to base ABCs.

这篇关于列表子类化的Pythonic方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆