2017-10-10 1 views
2

Ich habe beobachtet, dass ich bestimmte Integer-Werte in ihre Flag-zerlegten Typen konvertieren kann, und dass ich Flag-String-Namen in Flags konvertieren kann, aber ich habe noch nicht herausgefunden, ob es eine Möglichkeit gibt, eine String-Union von Flag-Namen zu konvertieren zu einem enum.Flag.Gibt es eine Möglichkeit, eine Zeichenfolge, die mehrere Flag-Mitglieder darstellt, in ein zusammengesetztes enum.Flag zu konvertieren?

import enum 
flag = enum.Flag('flg' , ['a', 'b', 'c', 'd']) 

# Valid 1:1 conversions... 
>>> flag["a"] 
<flg.a: 1> 
>>> flag["b"] 
<flg.b: 2> 
>>> flag(1) 
<flg.a: 1> 
>>> flag(2) 
<flg.b: 2> 

# Valid union int conversion 
>>> flag(7) 
<flg.c|b|a: 7> 
>>> flag(15) # largest integer flag can represent (1+2+4+8) 
<flg.d|c|b|a: 15> 

# Out of bounds 
>>> flag(16) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "C:\Anaconda3\lib\enum.py", line 291, in __call__ 
    return cls.__new__(cls, value) 
    File "C:\Anaconda3\lib\enum.py", line 533, in __new__ 
    return cls._missing_(value) 
    File "C:\Anaconda3\lib\enum.py", line 673, in _missing_ 
    possible_member = cls._create_pseudo_member_(value) 
    File "C:\Anaconda3\lib\enum.py", line 688, in _create_pseudo_member_ 
    raise ValueError("%r is not a valid %s" % (value, cls.__name__)) 
ValueError: 16 is not a valid flg 

Ich hatte gehofft, ich könnte etwas im Geiste der flag["d|c|b|a"], sondern ein Wörterbuch diese Umwandlung funktioniert nur für unterschiedliche Flagge Elementnamen, nicht jede Ansammlung von ihnen abziehen können. In der Zwischenzeit mache ich den Split, Convert, Union Merge manuell, aber ich bin gespannt, ob es einen direkteren Weg gibt, wie es der Int-Conversion-Fall kann.

EDIT: an der Quelle der Suche nach enum.py, scheint es, die korrekte Terminologie nicht Vereinigung ist aber Verbund

# enum.py 
def _create_pseudo_member_(cls, value): 
    """ 
    Create a composite member iff value contains only members. 
    """ 

Antwort

2

Sie enum.Flag Unterklasse könnte und seine _missing_() Methode abfangen:

from functools import reduce 

import enum 


class UnionFlag(enum.Flag): 

    @classmethod 
    def _missing_(cls, value): 
     if isinstance(value, str): 
      return reduce(cls.__or__, (cls[s] for s in value.split('|'))) 
     else: 
      return super()._missing_(value) 

>>> flag = UnionFlag('uflg', ['a', 'b', 'c', 'd']) 
>>> flag.a 
<uflg.a: 1> 
>>> flag(3) 
<uflg.b|a: 3> 
>>> flag['c'] 
<uflg.c: 4> 
>>> flag('a|b|d') 
<uflg.d|b|a: 11> 
Verwandte Themen