pythonでの反射

19069 ワード

python反射の概要
反射とは、文字列でオブジェクトを取得し、オブジェクトのプロパティまたはメソッドを実行することです.pythonではすべてオブジェクトなので、私たちはすべてのものを発射することができます.
反射pythonについては、4つの方法があります.
hasattr(object,name):nameは文字列でなければなりません.文字列nameがobjectオブジェクトの属性またはメソッドである場合、Trueが返されます.そうでない場合、Falseが返されます.
getattr(object,name,default=None):nameは文字列でなければなりません.文字列nameがobjectオブジェクトの属性である場合、またはメソッドが対応する属性またはメソッドを返します.そうしないと、デフォルト値が与えられた場合、デフォルト値が返され、デフォルト値が指定されていない場合、AttributeErrorの例外が発生します.
setattr(object,name,value):オブジェクトのプロパティを追加または変更できます.nameは文字列でなければなりません.valueは任意のデータ型です.nameがobjectのプロパティの場合、対応するプロパティの値がvalueに変更され、オブジェクトがobjectのプロパティでない場合、新しいプロパティが追加されます.
delattr(object,name):オブジェクト属性を削除します.nameは文字列でなければなりません.nameはobjectの属性でなければなりません.objectはこの属性を削除する権限があります.そうしないと、AttributeErrorが発生します.
次に、オブジェクトの反射、クラスの反射、現在のモジュールの反射、他のモジュールの反射を例に、反射の適用について説明します.
クラスの反射
class A:
    num = 10
    def fun(self):
        print('Hello World')
#   A    fun     
if hasattr(A,'fun'):
    #   fun       
    f = getattr(A,'fun')
    #   A fun   
    f('')
#       
Hello World

#  A     buf
setattr(A,'buf',[1,2,3])
print(A.buf)
#       
[1, 2, 3]

#       num
delattr(A,'num')
print(A.num)
#       
AttributeError: type object 'A' has no attribute 'num'

オブジェクトを反射する
class A:
    num = 10
    def fun(self):
        print('Hello World')
obj = A()
#     obj    fun  
if hasattr(obj,'fun'):
    #      fun       
    f = getattr(obj,'fun')
    #   obj fun  
    f()
#       
Hello World
#    obj    buf
setattr(obj,'buf',[1,2,3])
print(obj.buf)
#       
[1, 2, 3]
#   obj   buf
delattr(obj,'buf')
#    A   num
delattr(obj,'num')
#       
delattr(obj,'num')
AttributeError: num

  :obj  A      ,         ,  A      ,obj      A      ,     A              。

現在のモジュールを送信
import sys
class A:
    num = 10
    def fun(self):
        print('Hello World')
def f():
    print('         ')

#       
current_module = sys.modules[__name__]

#          A
if hasattr(current_module,'A'):
    obj_A = getattr(current_module,'A')
    obj_A.fun('')

#           f
if hasattr(current_module,'f'):
    obj_f = getattr(current_module,'f')
    obj_f()

#       
Hello World
         

他のモジュールを反射
# 1.py test.py    
============================
# test.py     
class A:
    num = 10
    def fun(self):
        print('Hello World')
def f():
    print('         ')
============================
# 1.py     
#      
import test
#   test.py     A
if hasattr(test,'A'):
    obj_A = getattr(test,'A')
    obj_A.fun('')

#   test.py      f
if hasattr(test,'f'):
    obj_f = getattr(test,'f')
    obj_f()

#       
Hello World
         

#      
imp_module = __import__('test')
#   test.py     A
if hasattr(imp_module,'A'):
    obj_A = getattr(imp_module,'A')
    obj_A.fun('')

#   test.py      f
if hasattr(imp_module,'f'):
    obj_f = getattr(imp_module,'f')
    obj_f()

#       
Hello World
         

getattr(object,name,default=None)のパラメータdefaultについては、位置パラメータで直接パラメータをパスすればよいので、キーワードパラメータでパラメータをパスしないでください.そうしないと、エラーが発生します.
class A:
    num = 10
    def fun(self):
        print('Hello World')

# getattr       
obj = getattr(A,'max','   ')
print(obj)
#       
   

# getattr       
obj = getattr(A,'max',default='   ')
#       
TypeError: getattr() takes no keyword arguments

反射の適用
上のコードクリップを見ると、反射もそうではないと感じるかもしれませんが、シーンによっては反射が本当に役に立ちます.以下はFTP serverとFTP clientを例に、私が前に書いた小さな練習です.
興味のある方はご覧ください.https://www.cnblogs.com/caesar-id/p/12105321.htmlサービス側はクライアントからのコマンドを解析する際に使用する反射であり,反射しなければクライアントがどのコマンドを実行するかを解析するために大量のifを使用する必要がある.
次に、反射を使用せずにクライアントからのコマンド(疑似コード)を解析します.
class DataAnalysis(FileOperation):
    """
           ,      client       。
    """
    def syntax_analysis(self,recv_data, socket_obj, commom):
        """
                    。
        :param recv_data:        
        :param socket_obj:socket  
        :param commom:    
        :return:
        """
        #            help     get              cd   
        #
        #
        clientData = recv_data.split(" ")
        if clientData[0] == 'help':
            pass
        elif clientData[0] == 'get':
            pass
        elif clientData[0] == 'cd':
            pass
        elif clientData[0] == 'put':
            pass
        ...

上記の状況は明らかにプログラムがどれだけの機能を持っているか、どれだけのifが必要かを判断し、ある方法が変更されたり、機能が追加されたりした場合、ifに相応の論理判断を追加したり、対応する論理を修正したりする必要があり、コードの読み取りから後期のメンテナンスに至るまで不便である.
次に、反射を使用してクライアントからのコマンドを解析します.
class DataAnalysis(FileOperation):
    """
           ,      client       。
    """
    def syntax_analysis(self,recv_data, socket_obj, commom):
        """
                    。
        :param recv_data:        
        :param socket_obj:socket  
        :param commom:    
        :return:
        """
        #            help     get              cd   
        #
        #
        clientData = recv_data.split(" ")
        if hasattr(self, clientData[0]):  #              
            get_fun = getattr(self, clientData[0])  #          
            get_fun(clientData, socket_obj, commom)  #        
        else:
            pass

反射を使用してクライアントコマンドを解析するには、プログラムがどんなに方法があっても、上のコード数行だけでいいです.ifによる命令解析反射構造よりも明確であり,ある方法が変更されたり,新しい機能が追加されたりすると,すべての精力を機能実現に費やすだけでよく,ifのように論理を追加したり,対応する論理を修正したりする必要がなく,メンテナンスが容易である.ここまで反射して簡単に紹介します.