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

让我们构造一个示例:

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

如您所见,我已经在使用IntEnum来获取该枚举的算术功能。最好使用@unique这样的东西来确保所有值都是2的幂。我可以通过 fork enum.unique来实现此目的。 (我知道All是该规则的异常(exception)。)

如何使用这样的枚举?
filter = NetlistKind.LatticeNetlist | NetlistKind.QuartusNetlist

由于采用了底层int位,因此可以进行位操作,并且filter的内部值为3。

如果有一个“在过滤器Y中设置X标记”功能,或者甚至是一个更好的运算符,将是一个很好的选择。我为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版本? :)

  • 开放功能:
  • 返回__str__中所有 Activity 标志的列表
  • ...?
  • 最佳答案

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

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

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

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

    由于通过库声明的标志类会自动提供两个“虚拟”标志:NetlistKind.no_flagsNetlistKind.all_flags,因此上述操作可能需要进一步调整。这些使已经声明的NetlistKind.UnknownNetlistKind.All变得多余,因此我们可以将它们从声明中删除,但是问题是no_flagsall_flags与您的命名约定不匹配。为此,我们在您的项目中声明一个flags基类,而不是flags.Flags,您将不得不在项目的其余部分中使用它:
    from flags import Flags
    
    class BaseFlags(Flags):
        __no_flags_name__ = 'Unknown'
        __all_flags_name__ = 'All'
    

    基于先前声明的基类,该基类可以被您项目中的任何标志所继承,我们可以将标志声明更改为:
    class NetlistKind(BaseFlags):
        LatticeNetlist = 1
        QuartusNetlist = 2
        XSTNetlist = 4
        CoreGenNetlist = 8
    

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

    作为使用“函数调用样式”的替代声明(也由标准枚举模块提供):
    NetlistKind = BaseFlags('NetlistKind', ['LatticeNetlist', 'QuartusNetlist',
                                            'XSTNetlist', 'CoreGenNetlist'])
    

    如果标志类声明了一些成员,则将其视为最终成员。尝试对其进行子类化将导致错误。从语义上讲,为了添加新成员或更改功能,不允许子类化flag类。

    除此之外,flags类还以类型安全的方式向您提供列出的运算符( bool(boolean) 运算符,in,迭代等)。在接下来的几天中,我将完成README.rst并在包接口(interface)上进行一些设置,但是基本功能已经存在并且已经进行了很好的测试。

    关于python-3.x - 是否有用于标记/位掩码操作的Python类/枚举?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/36829820/

    10-12 20:25