整数値の各ビットをフラグと見なすことで整数値をフラグの集合として扱う Python のクラスを実装してみた。
役に立つことは少なそう。
実装
class IntFlags:
"""整数値をフラグの集合として扱うためのクラス"""
_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")]))
継承してこういうクラスを作ると、以下のように扱える。
# 初期化
user_permission = UnixPermission(6)
user_permission #=> <UnixPermission "rw-">
# 個別のフラグにアクセス
user_permission.read #=> True
# 個別のフラグを書き換え
user_permission.execute = True
user_permission #=> <UnixPermission "rwx">
# 整数値に戻す
int(user_permission) #=> 7