88992


### 目的

dot(`.`)で区切られたIPv4のサブネットマスク文字列がサブネットマスクとして有効であることを判定したい。

### 判定例

[code]

    '255.128.0.0'->'1111 1111 1000 0000 0000 0000 0000 0000' :OK
    '255.64.0.0.'->'1111 1111 0100 0000 0000 0000 0000 0000' :NG
    
[/code]

### 質問内容

下記ソースコードで機能的に満足しますが、もっとエレガントな記述方法があると思うので、ご教示をお願いしたいです。

ソースコード

[code]

    import re
    
    
    def chk(subnetmask):
        chk_string = re.compile(
            r"[0-9]{1,3}[.]{1}[0-9]{1,3}[.]{1}[0-9]{1,3}[.]{1}[0-9]{1,3}", re.A)
    
        if chk_string.fullmatch(subnetmask):
            mask_octet = subnetmask.split(".")
            mask_octet = list((map(int, mask_octet)))
    
            mask = 0
            for i, n in enumerate(mask_octet):
                mask += n*2**(8*(3-i))
    
            # 2進数文字列変換 接頭文字は削除
            bmask = bin(mask)
            bmask = bmask.lstrip("0b")
    
            # 32bit 先頭bit=1なら文字列長8bitx4oct=32のはず。
            if len(bmask) == 8*4:
                # 文字1のカウント
                count1 = bmask.count('1')
                # 32bitの1ではないはずの桁数部分を削除するために除算
                # いわゆるビットシフト
                lmask = bin(int(mask/(2**(8*4-count1))))
                lmask = lmask.lstrip("0b")
                c1 = lmask.count('1')
                # 前詰めなら同数になるはず
                if count1 == c1:
                    return True
        return False
    
[/code]


CC BY-SA 4.0
2022-05-23T06:44:57.217
88990
2022-05-24T13:07:26.030
2022-05-23T07:37:51.693
3060
32891
question
python network
Python で IPv4 のサブネットマスク文字列の判定をしたい

[code]

    import ipaddress
    
    def chk(subnetmask):
        try:
            ipaddress.IPv4Network((0, subnetmask))
            return True
        except ipaddress.NetmaskValueError:
            return False
    
    if __name__ == '__main__':
        print(chk('255.128.0.0'))
        print(chk('255.64.0.0'))
    
    #
    True
    False
    
[/code]


CC BY-SA 4.0
2022-05-23T07:19:35.693
88992
2022-05-23T07:19:35.693
47127
88990
answer


本来は標準モジュール使うほうが簡単で便利だけど, 自分で実装してみるのも演算子の勉強になったりするかもです。  
標準モジュールはこちら。

  * (Python HOWTO) [ipaddressモジュールの紹介](https://docs.python.org/ja/3/howto/ipaddress.html)
  * [ipaddress --- IPv4/IPv6 操作ライブラリ](https://docs.python.org/ja/3/library/ipaddress.html)

ネットマスクは, 30種類程度ならすべて保持しておいて, どれか HITするか調べるのも手かも。

[code]

    allff = 0xffffffff
    lst = [(~((1 <<n) -1)) &allff for n in range(2, 32)]
    for msk in lst:
        pattern = f'{msk:b}'
        print(pattern)
    
    # 出力
    11111111111111111111111111111100
    11111111111111111111111111111000
    11111111111111111111111111110000
    11111111111111111111111111100000
    11111111111111111111111111000000
    11111111111111111111111110000000
    11111111111111111111111100000000
    (略)
    
[/code]


CC BY-SA 4.0
2022-05-24T13:07:26.030
89026
2022-05-24T13:07:26.030
43025
88990
answer