I implemented a Python class that treats integer values as a set of flags by treating each bit of the integer value as a flag.
It seems to be rarely useful.
class IntFlags:
    """A class for treating integer values as a set of flags"""
    _alias = []
    def __init__(self, state: int = 0):
        if state < 0:
            raise ValueError
        object.__setattr__(self, "_state", state)
    def __getitem__(self, digit: int) -> bool:
        return (self._state & (1 << digit)) > 0
    def __setitem__(self, digit: int, value: bool):
        if type(value) is not bool:
            raise TypeError
        if self[digit] != value:
            object.__setattr__(self, "_state", self._state ^ (1 << digit))
    def __getattr__(self, key: str) -> bool:
        alias = type(self)._alias
        if key not in alias:
            raise AttributeError
        return self[alias.index(key)]
    def __setattr__(self, key: str, value: bool):
        alias = type(self)._alias
        if key not in alias:
            raise AttributeError
        self[alias.index(key)] = value
    def __int__(self) -> int:
        return self._state
    def __str__(self) -> str:
        return f"{self._state:0{len(type(self)._alias)}b}"
    
    def __repr__(self) -> str:
        return f'<{type(self).__name__} "{str(self)}">'
class UnixPermission(IntFlags):
    _alias = ["execute", "write", "read"]
    
    def __str__(self) -> str:
        return "".join(reversed([char if self[idx] else "-" for idx, char in enumerate("xwr")]))
If you inherit and create such a class, you can handle it as follows.
#Initialize
user_permission = UnixPermission(6)
user_permission  #=> <UnixPermission "rw-">
#Access individual flags
user_permission.read  #=> True
#Rewrite individual flags
user_permission.execute = True
user_permission  #=> <UnixPermission "rwx">
#Revert to an integer value
int(user_permission)  #=> 7
        Recommended Posts