Pythonでの魔法の使い方の勉強

6353 ワード

概念解析
魔法の方法はpythonの高度な文法で、彼らはあなたのクラスに「magic」を追加することができる特殊な方法です.例えば、追加の機能を追加します.関数の形式は_xx _(二重下線で囲まれた関数).
魔法の方法
  • 基本カスタマイズ
  • object.__init__(self, *args, **kwargs)  #    ,        ,          
    object.__new__(cls, *args, **kwargs)    #    ,       ,        
    object.__del__(self)                    #    ,       
    object.__str__(self)                    #   C      , str(C())       
    object.__len__(self)                    #   C      , len(C())       
    

    テストコードは次のとおりです.
    # coding=utf-8
    class MagicDemo(object):
        def __init__(self):
            """              """
            print "call me second"
            self.value = [1, 2, 3]
    
        def __new__(cls, *args, **kwargs):
            """
                   ,  __init__  ,
                   
            """
            print "call me first"
            return super(MagicDemo, cls).__new__(cls, *args, **kwargs)
    
        def __del__(self):
            print "call __del__"
            del self
    
        def __len__(self):
            print "call __len__"
            return len(self.value)
    
        def __str__(self):
            return "call __str__"
    if __name__ == '__main__':
        mag = MagicDemo()
        print mag.value
        print len(mag)
        print str(mag)
        del mag
    

    実行結果は次のとおりです.
    call me first
    call me second
    [1, 2, 3]
    call __len__
    3
    call __str__
    call __del__
    
  • 比較関数
  • object.__lt__(self, obj)                #      <
    object.__le__(self, obj)                #       <=
    object.__gt__(self, obj)                #    >
    object.__ge__(self, obj)                #       >=
    object.__eq__(self, obj)                #    ==
    object.__ne__(self, obj)                #     !=
    

    テストコードは次のとおりです.
    # coding=utf-8
    class MagicDemo(object):
        def __init__(self, value):
            self.value = value
    
        def __lt__(self, obj):
            print "call the __lt__"
            return self.value < obj.value
    
        def __le__(self, obj):
            print "call the __le__"
            return self.value <= obj.value
    
        def __gt__(self, obj):
            print "call the __gt__"
            return self.value > obj.value
    
        def __ge__(self, obj):
            print "call the __ge__"
            return self.value >= obj.value
    
        def __eq__(self, obj):
            print "call the __eq__"
            return self.value == obj.value
    
        def __ne__(self, obj):
            print "call the __ne__"
            return self.value != obj.value
    if __name__ == '__main__':
        mag1 = MagicDemo(5)
        mag2 = MagicDemo(6)
        print mag1 < mag2
        print mag1 <= mag2
        print mag1 > mag2
        print mag1 >= mag2
        print mag1 == mag2
        print mag1 != mag2
    

    実行結果は次のとおりです.
    call the __lt__
    True
    call the __le__
    True
    call the __gt__
    False
    call the __ge__
    False
    call the __eq__
    False
    call the __ne__
    True
    
  • 属性操作
  • object.__getattr__(self, attr)                   #     ,           
    object.__setattr__(self, attr, val)              #     ,           
    object.__delattr__(self, attr)                   #         
    object.__getattribute__(self, attr)              #     ,     ,       __getattr__
    object.__get__(self, attr)                       #(   )    
    object.__set__(self, attr, val)                  #(   )    
    object.__delete__(self, attr)                    #(   )    
    

    テストコード(記述子の3つのプロパティは説明を省略)
    # coding=utf-8
    class MagicDemo(object):
        def __init__(self, value):
            self.value = value
    
        def __getattr__(self, attr):
            """         """
            print "call __getattr__"
            return "%s no found" % attr
    
        def __setattr__(self, attr, value):
            print "call __setattr__"
            self.__dict__[attr] = value
    
        def __delattr__(self, attr):
            print "call __delattr__"
            del self.__dict__[attr]
    
        def __getattribute__(self, attr):
            """          """
            print "call __getattribute__"
            # return self.__dict__[name]
            #          
            return object.__getattribute__(self, attr)
    if __name__ == '__main__':
        mag = MagicDemo(5)
        print "_______________"
        mag.value = 6
        print "_______________"
        print mag.value
        print "_______________"
        print mag.xxx
    

    テスト結果は次のとおりです.
    call __setattr__
    call __getattribute__
    _______________
    call __setattr__
    call __getattribute__
    _______________
    call __getattribute__
    6
    _______________
    call __getattribute__
    call __getattr__
    xxx no found
    

    オブジェクトのプロパティにアクセスすると、__getattribute__は常に呼び出され(新しいクラスで有効)、プロパティが見つからないと__getattr__が呼び出されることがわかります.ここで、__getattribute__がベースクラスを呼び出す方法は、__getattribute__が常に無条件に呼び出されるため、デッドサイクルに陥るためである.
  • カスタムシーケンス
  • object.__getitem__(self, key)                    #         
    object.__setitem__(self, key, val)               #         
    object.__delitem__(self, key)                    #         
    object.__contains__(self, key)                   #       ,  in   
    object.__iter__(self)                            #        
    

    テストコード:
    # coding=utf-8
    class MagicDemo(object):
        def __init__(self):
            self.value = dict()
    
        def __getitem__(self, key):
            print "call the __getitem__"
            return self.value[key]
    
        def __setitem__(self, key, val):
            print "call the __setitem__"
            self.value[key] = val
    
        def __delitem__(self, key):
            print "call the __delitem__"
            del self.value[key]
    
        def __contains__(self, key):
            print "call the __contains__"
            return key in self.value
    
    if __name__ == '__main__':
        mag = MagicDemo()
        mag["name"] = "hello"
        print "_______________"
        print mag["name"]
        print "_______________"
        print "xxx" in mag
    

    テスト結果は次のとおりです.
    call the __setitem__
    _______________
    call the __getitem__
    hello
    _______________
    call the __contains__
    False
    

    なお、属性がdictの場合はキー値対で付与し、listの場合は下付き文字で付与する.