是否有用于标记/位掩码操作的Python类/枚举? [英] Is there a Python class/enum for flag/bit mask operations?

查看:58
本文介绍了是否有用于标记/位掩码操作的Python类/枚举?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道基本类 Enum IntEnum 。两者都非常有用,但是我错过了标志操作的功能。我不希望这两个类实现我希望的功能。

I know of base classes Enum and IntEnum. Both are very helpful but I miss features for flag operations. I don't expect that these two classes implement my wished feature.

让我们构造一个示例:

class NetlistKind(IntEnum):
  Unknown = 0
  LatticeNetlist = 1
  QuartusNetlist = 2
  XSTNetlist = 4
  CoreGenNetlist = 8
  All = 15

如您所见,我已经在使用 IntEnum 获取此枚举的算术功能。最好使用 @unique 之类的东西来确保所有值都是2的幂。我可以通过为我的需要派生enum.unique来做到这一点。 (我知道 All 是该规则的例外。)

As you can see, I'm already using IntEnum to get arithmetic features for this enum. It would be nice to have something like @unique to ensure all values are a power of two. I can do this by forking enum.unique for my needs. (I'm aware that All is an exception from that rule.)

如何使用这种枚举?

filter = NetlistKind.LatticeNetlist | NetlistKind.QuartusNetlist

感谢底层int位操作的实现,并且filter的内部值为3。

Thanks to the underlaying int bit operations are possible and filter has an internal value of 3.

如果最好在过滤器Y中设置标志X设置,或者最好是一个运算符。我为y中的 x添加了一个魔术函数

If would be nice to have a "is flag X set in filter Y" function or even better an operator. I add a magic function for x in y:

@unique
class NetlistKind(IntEnum):
  Unknown = 0
  LatticeNetlist = 1
  QuartusNetlist = 2
  XSTNetlist = 4
  CoreGenNetlist = 8
  All = 15

def __contains__(self, item):
  return  (self.value & item.value) == item.value

用法示例:

....
def GetNetlists(self, filter=NetlistKind.All):
  for entity in self._entities:
    for nl in entity.GetNetlists():
      if (nl.kind in filter):
        yield nl

def GetXilinxNetlists(self):
  return self.GetNetlists(NetlistKind.XSTNetlist | NetlistKind.CoreGenNetlist)

所以问题是:


  • 是否有更好的方法来实现位

  • 有没有更好的方法来实现这样的一维滤波器?我不想对这样的简单过滤条件使用lamda?

  • Python标准库中已经包含了这样的解决方案吗?

  • 如何将此枚举扩展添加到下一个Python版本吗? :)

  • Are there better ways to implement bit fields?
  • Are thete better ways to implement such an 1-D filter? I don't want to use lamdas for such a simple filter condition?
  • Is such solution already included in the Python standard library?
  • How to add this enum extension to the next Python version? :)

打开功能:


  • 返回 __ str __

  • ...?

推荐答案

我最近发布了一个开源软件包 py-flags 。该库正是具有此功能,并且其设计在很大程度上受到python3枚举模块的影响。

I've recently published an opensource package py-flags that aims this problem. That library has exactly this functionality and its design is heavily influenced by the python3 enum module.

关于它是否具有足够的pythonic来实现这样的flags类存在争议。功能与该语言提供的其他方法(布尔变量,集合,具有布尔属性的对象或具有布尔项的字典等的集合)有很大的重叠。因此,我觉得flags类的用途太狭窄和/或多余,以致无法进入标准库,但是在某些情况下,它比以前列出的解决方案好得多,因此可以使用 pip install库

There are debates about whether it is pythonic enough to implement such a flags class because its functionality has huge overlaps with other methods provided by the language (collection of bool variables, sets, objects with bool attributes or dicts with bool items, ...). For this reason I feel a flags class to be too narrow purpose and/or redundant to make its way to the standard library but in some cases it is much better than the previously listed solutions so having a "pip install"-able library can come in handy.

使用py-flags模块,您的示例如下所示:

Your example would look like the following using the py-flags module:

from flags import Flags

class NetlistKind(Flags):
    Unknown = 0
    LatticeNetlist = 1
    QuartusNetlist = 2
    XSTNetlist = 4
    CoreGenNetlist = 8
    All = 15

以上可能是进行了进一步调整,因为在库中声明的标志类自动提供了两个虚拟标志: NetlistKind.no_flags NetlistKind.all_flags 。这些使已经声明的 NetlistKind.Unknown NetlistKind.All 变得多余,因此我们可以将它们从声明中删除,但是问题是 no_flags all_flags 与您的命名约定不匹配。为此,我们在您的项目中声明一个flags基类,而不是 flags.Flags ,您将不得不在项目的其余部分中使用它:

The above things could be tweaked a bit further because a flags class declared with the library automatically provides two "virtual" flags: NetlistKind.no_flags and NetlistKind.all_flags. These make the already declared NetlistKind.Unknown and NetlistKind.All redundant so we could leave them out from the declaration but the problem is that no_flags and all_flags don't match your naming convention. To aid this we declare a flags base class in your project instead of flags.Flags and you will have to use that in the rest of your project:

from flags import Flags

class BaseFlags(Flags):
    __no_flags_name__ = 'Unknown'
    __all_flags_name__ = 'All'

基于先前声明的基类,该基类可以由您的任何标志进行子类化您的项目,我们可以将您的标志声明更改为:

Based on the previously declared base class that can be subclassed by any of your flags in your project we could change your flag declaration to:

class NetlistKind(BaseFlags):
    LatticeNetlist = 1
    QuartusNetlist = 2
    XSTNetlist = 4
    CoreGenNetlist = 8

这种方式 NetlistKind.Unknown 会自动声明为零。 NetlistKind.All 也在那里,它自动是所有已声明标志的组合。可以使用/不使用这些虚拟标志来迭代枚举成员。您还可以声明别名(与另一个先前声明的标志具有相同值的标志)。

This way NetlistKind.Unknown is automatically declared with a value of zero. NetlistKind.All is also there and it is automatically the combination of all of your declared flags. It is possible to iterate enum members with/without these virtual flags. You can also declare aliases (flags that have the same value as another previously declared flag).

作为使用函数调用样式的替代声明(也提供了标准枚举模块):

As an alternative declaration using the "function-call style" (also provided by the standard enum module):

NetlistKind = BaseFlags('NetlistKind', ['LatticeNetlist', 'QuartusNetlist',
                                        'XSTNetlist', 'CoreGenNetlist'])

如果flags类声明了某些成员,则将其视为最后。尝试对其进行子类化将导致错误。出于语义上的考虑,不允许出于允许添加新成员或更改功能的目的而对flag类进行子类化。

If a flags class declares some members then it is considered to be final. Trying to subclass it will result in error. It is semantically undesired to allow subclassing a flag class for the purpose of adding new members or change functionality.

除此之外,flags类还为您列出的操作符(布尔操作符, in,迭代等...)。在接下来的几天中,我将完成README.rst并在软件包界面上进行一些设置,但是基本功能已经存在并且已经过相当不错的测试。

Besides this the flags class provides the operators your listed (bool operators, in, iteration, etc...) in a type-safe way. I'm going to finish the README.rst along with a little plumbing on the package interface in the next few days but the basic functionality is already there and tested with quite good coverage.

这篇关于是否有用于标记/位掩码操作的Python类/枚举?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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