Scapyのコードを少しみてみる。特殊メソッド__div__, __getitem__ とかのオーバロード。


目的

少し用事があり、例えば、Scapyのコードはどんな感じが見てみた。
Scapyとは、
Scapy is a powerful Python-based interactive packet manipulation program and library.
(引用:https://pypi.org/project/scapy/)

Pythonの素人?(詳しくない意)の、ワタシには、かなり難しいコードでした。

まず、特殊メソッドのオーバロードあたりで、コードが
理解できなくなった
ので、わかったことをこの記事のメモにする。

わかったこと

引用コードは、すべて、
https://github.com/secdev/scapy
から。

__div__ のオーバロード

使い方:

    a = IP(dst=dest) / TCP(flags="S", seq=i, sport=65000, dport=55556)
    b = IP(dst=dest)/ICMP()

作用:
オブジェクトを「/」で、くっつける。

以下のような感じのコードでオーバロードされている。

    def __div__(self, other):
        if isinstance(other, Packet):
            cloneA = self.copy()
            cloneB = other.copy()
            cloneA.add_payload(cloneB)
            return cloneA
        elif isinstance(other, (bytes, str)):
            return self / conf.raw_layer(load=other)
        else:
            return other.__rdiv__(self)

__getitem__のオーバロード

使い方:

        seq = pkt[TCP].seq

作用:
[ ]で、一部を取り出す。

以下のような感じのコードでオーバロードされている。

    def __getitem__(self, cls):
        if isinstance(cls, slice):
            lname = cls.start
            if cls.stop:
                ret = self.getlayer(cls.start, nb=cls.stop, **(cls.step or {}))
            else:
                ret = self.getlayer(cls.start, **(cls.step or {}))
        else:
            lname = cls
            ret = self.getlayer(cls)
        if ret is None:
            if isinstance(lname, Packet_metaclass):
                lname = lname.__name__
            elif not isinstance(lname, bytes):
                lname = repr(lname)
            raise IndexError("Layer [%s] not found" % lname)
        return ret

まとめ

上記のオーバーロードは、便利に見えるので、他のモジュールとかでも使われているかも。
役立つかもしれない情報は、以下。

  • a[iii] のメソッド名は、 __getitem__ です。

コメントなどあれば、お願いします。
この程度の処理は、他の言語でも沢山あるのかも。。Cぐらいしかわかっていないワタシには、基本的な記号(オペレータ)がオーバロードされると、多少、戸惑う。