MACアドレスは, デバイスの固有住所や固有名詞的な立ち位置なので, 個人情報に該当すると扱われ, しばしば暗号化して管理することがあります。
MACアドレスの暗号化を自前で実装したり, 解いたりする場合には, 四則演算することが必要です。
今回は, Pythonでoperator overloadingとクラス継承を使って, これらを実装しましょう。
operator overloadingについては, こちらの記事を参考にしてください。
operator overloadでオリジナルの演算子を実装 for Python - werry-chanの日記.料理とエンジニアリング
まずは, 親クラスとして, 符号なしN進数クラスを作ります。
class unsigned_int:
def __init__(self, val, upper_lim=256):
self.val = val
self.upper_lim = upper_lim
self.check_val()
def show(self):
print(self.val, end="")
def check_val(self):
self.val = int(self.val % self.upper_lim)
表示 show() 関数とN進数チェック check_val() 関数も作っておきました。
次はこのクラス間で四則演算できるように, 演算子を定義します。
import copy
class unsigned_int:
def __init__(self, val, upper_lim=256):
self.val = val
self.upper_lim = upper_lim
self.check_val()
def show(self):
print(self.val, end="")
def check_val(self):
self.val = int(self.val % self.upper_lim)
def to_myclass(self, val):
temp = copy.deepcopy(self)
temp.val = val
return temp
def __add__(self, add_uint):
if type(self) != add_uint.__class__:
add_uint = self.to_myclass(add_uint)
ret_uint = copy.deepcopy(self)
ret_uint.val += add_uint.val
ret_uint.check_val()
return ret_uint
def __sub__(self, sub_uint):
if type(self) != sub_uint.__class__:
sub_uint = self.to_myclass(sub_uint)
ret_uint = copy.deepcopy(self)
ret_uint.val -= sub_uint.val
ret_uint.check_val()
return ret_uint
def __mul__(self, mul_uint):
if type(self) != mul_uint.__class__:
mul_uint = self.to_myclass(mul_uint)
ret_uint = copy.deepcopy(self)
ret_uint.val *= mul_uint.val
ret_uint.check_val()
return ret_uint
def __truediv__(self, dev_uint):
if type(self) != dev_uint.__class__:
dev_uint = self.to_myclass(dev_uint)
ret_uint = copy.deepcopy(self)
ret_uint.val /= dev_uint.val
ret_uint.check_val()
return ret_uint
class unsigned_hex(unsigned_int):
def __init__(self, val):
super().__init__(val, upper_lim=8)
class unsigned_oct(unsigned_int):
def __init__(self, val):
super().__init__(val, upper_lim=16)
演算子を定義するついでに, クラス継承で8進数と16進数を作っておきました。
それでは, 目的のMACアドレスのクラスを作ってみましょう。
典型的なMACアドレスは
F1:10:0B:16:FD:3A
のように, 16進数 2桁 6個で構成されています。
先ほど作成したunsigned_intクラスを使って実装します。
16進数2桁なので, 256=16^2, unsigned_intのupper_limはdefault引数256が使えますので, 省略可能です。
今回は入力される文字列にspace, tabなどは考慮せず, 必ず2桁以下, 正の値で入力されることを前提に実装していきます。
class mac_address:
def __init__(self, str_digits, digits=6, upper_lim=256):
self.digits = digits
self.val_list = str_digits.split(':')
for i in range(len(self.val_list)):
self.val_list[i] = unsigned_int( int('0x' + str(self.val_list[i]), 0) )
def show(self):
for i in range(len(self.val_list)):
self.val_list[i].show(); print(",", end="")
__init__()初期化関数でlistに各値を保持しています。
16進数の文字列の先頭に'0x'をつけてint('0x' + str(val), 0)としてやると
文字列からintの数値として読み込めます。
では先ほどの符号なしN進数の実装と同様に演算子を作成しましょう。
class mac_address:
def __init__(self, str_digits, digits=6, upper_lim=256):
self.digits = digits
self.val_list = str_digits.split(':')
for i in range(len(self.val_list)):
self.val_list[i] = unsigned_int( int('0x' + str(self.val_list[i]), 0) )
def show(self):
for i in range(len(self.val_list)):
self.val_list[i].show(); print(",", end="")
def __add__(self, add_digits):
ret_digits = copy.deepcopy(self)
for i in range(self.digits):
ret_digits.val_list[i] += add_digits.val_list[i]
return ret_digits
def __sub__(self, sub_digits):
ret_digits = copy.deepcopy(self)
for i in range(self.digits):
ret_digits.val_list[i] -= sub_digits.val_list[i]
return ret_digits
def __mul__(self, mul_digits):
ret_digits = copy.deepcopy(self)
for i in range(self.digits):
ret_digits.val_list[i] *= mul_digits.val_list[i]
return ret_digits
def __truediv__(self, dev_digits):
ret_digits = copy.deepcopy(self)
for i in range(self.digits):
ret_digits.val_list[i] /= dev_digits.val_list[i]
return ret_digits
やっとのことで演算可能なMACアドレスの自作クラスが完成しました。
普通はMACアドレスて基本は固定値か乱数なので, 演算しようとする人はいないので, めちゃくちゃ使いどころが限られるクラスになります。
自作するしかないですね。
以下に全コード載せておきます。
import copy
class unsigned_int:
def __init__(self, val, upper_lim=256):
self.val = val
self.upper_lim = upper_lim
self.check_val()
def show(self):
print(self.val, end="")
def check_val(self):
self.val = int(self.val % self.upper_lim)
def to_myclass(self, val):
temp = copy.deepcopy(self)
temp.val = val
return temp
def __add__(self, add_uint):
if type(self) != add_uint.__class__:
add_uint = self.to_myclass(add_uint)
ret_uint = copy.deepcopy(self)
ret_uint.val += add_uint.val
ret_uint.check_val()
return ret_uint
def __sub__(self, sub_uint):
if type(self) != sub_uint.__class__:
sub_uint = self.to_myclass(sub_uint)
ret_uint = copy.deepcopy(self)
ret_uint.val -= sub_uint.val
ret_uint.check_val()
return ret_uint
def __mul__(self, mul_uint):
if type(self) != mul_uint.__class__:
mul_uint = self.to_myclass(mul_uint)
ret_uint = copy.deepcopy(self)
ret_uint.val *= mul_uint.val
ret_uint.check_val()
return ret_uint
def __truediv__(self, dev_uint):
if type(self) != dev_uint.__class__:
dev_uint = self.to_myclass(dev_uint)
ret_uint = copy.deepcopy(self)
ret_uint.val /= dev_uint.val
ret_uint.check_val()
return ret_uint
class unsigned_hex(unsigned_int):
def __init__(self, val):
super().__init__(val, upper_lim=8)
class unsigned_oct(unsigned_int):
def __init__(self, val):
super().__init__(val, upper_lim=16)
class mac_address:
def __init__(self, str_digits, digits=6, upper_lim=256):
self.digits = digits
self.val_list = str_digits.split(':')
for i in range(len(self.val_list)):
self.val_list[i] = unsigned_int( int('0x' + str(self.val_list[i]), 0) )
def show(self):
for i in range(len(self.val_list)):
self.val_list[i].show(); print(",", end="")
def __add__(self, add_digits):
ret_digits = copy.deepcopy(self)
for i in range(self.digits):
ret_digits.val_list[i] += add_digits.val_list[i]
return ret_digits
def __sub__(self, sub_digits):
ret_digits = copy.deepcopy(self)
for i in range(self.digits):
ret_digits.val_list[i] -= sub_digits.val_list[i]
return ret_digits
def __mul__(self, mul_digits):
ret_digits = copy.deepcopy(self)
for i in range(self.digits):
ret_digits.val_list[i] *= mul_digits.val_list[i]
return ret_digits
def __truediv__(self, dev_digits):
ret_digits = copy.deepcopy(self)
for i in range(self.digits):
ret_digits.val_list[i] /= dev_digits.val_list[i]
return ret_digits
if __name__ == "__main__":
ui = unsigned_hex(5)
ui_ = unsigned_hex(7)
(ui_ - 20 ).val; print()
(ui / ui_).show; print()
ma0 = mac_address( '6:10:2B:C0:0D:34')
ma1 = mac_address('F1:10:0B:16:FD:3A')
ma0.show(); print()
ma1.show(); print()
(ma0 - ma1).show(); print()
(ma0 + ma1).show(); print()
(ma0 * ma1).show(); print()
(ma0 / ma1).show(); print()