2011-09-14 6 views
0

オブジェクトのインスタンス化中にインスタンスメソッドを動的にロードできるようにしたい。私の設計によると、デフォルトの動作はベースクラスにコード化されています。しかし、 オブジェクトの配置中に特定の条件が満たされた場合、私は動的に この動作を別のコードと変更します。オブジェクトのインスタンス化中にインスタンスメソッドを動的にロード

デフォルトの動作がfirst.pyでコーディングされています:上記のコードで

class First(object): 
    def __init__(self, p): 
     p = str(p) 
     #The decision whether or not to perform default action is done 
     #in the following try/except block. In reality this block 
     #is more complicated 
     #and more checks are performed in order to assure proper work 
     try: 
      strImport = "__import__('module%s')"%p 
      e = eval(strImport, {}, {}) 
      if not hasattr(e, p): 
       raise ImportError() 
     except ImportError: 
      e = None #default behaviour 
     if e is not None: 
      self.act = getattr(e, p)(p).act #special behaviour 
     self.p = p 

    def act(self): 
     print 'Default behaviour' 


import cPickle as pickle 



if __name__ == '__main__': 
    print 'first' 
    first = First('f') 
    first.act() 
    pickle.dump(first, open('first.dump', 'w')) 

    print 'third' 
    third = First('Third') 
    third.act() 
    pickle.dump(third, open('third.dump', 'w')) 

、両方 firstthirdデフォルトのアクションを実行するこれは私がそれを行う方法 です。次のように私は、ファイル moduleThird.pyを追加することにより、 thirdの 動作を変更することができます

from temp import First 
class Third(First): 
    def __init__(self, p): 
     p = 'Third *** %p' 
     print 'third init' 
     super(self.__class__, self).__init__(p) 


    def act(self): 
     super(self.__class__, self).act() 
     print 'Third acted' 

このファイルが追加された後、thirdはその動作を変更します。しかし、私は次のエラーのため、結果のオブジェクトをpickle化することができませんでし ないよ:

Traceback (most recent call last): 
    File "C:\temp\temp.py", line 35, in <module> 
    pickle.dump(fff, open('fff.dump', 'w')) 
    File "C:\Python26\lib\copy_reg.py", line 70, in _reduce_ex 
    raise TypeError, "can't pickle %s objects" % base.__name__ 
TypeError: can't pickle instancemethod objects 

動的にロードする方法Third.actは漬物に問題を引き起こしていることは明らかです。ピッキング可能なオブジェクト(さらにエレガントなコードも)を取得するために、私のアプローチを変更する必要がありますか?

私の目標を達成する良い方法はありますか?それが動作するはず次のようにあなたのコードを変更した場合

+0

は見てい「オブジェクト属性のピクルスが失敗したために伝えるためにどのように?」このサイトでどの部分が酸洗いできないのかを知る仲間ヘルプクラスの回答があります。 – Louis

+0

@ルイス、どの方法がピクルスの問題を引き起こすのか知っています(質問の最後に私の追加を見てください)。私はこれらの問題を解決する方法を探しています。 –

答えて

1

class First(object): 
    def __init__(self, p): 
     p = str(p) 
     #The decision whether or not to perform default action is done 
     #in the following try/except block. In reality this block 
     #is more complicated 
     #and more checks are performed in order to assure proper work 
     try: 
      strImport = "__import__('module%s')"%p 
      print strImport 
      e = eval(strImport, {}, {}) 
      if not hasattr(e, p): 
       raise ImportError() 

      self.override_obj = getattr(e, p)(p) 
     except ImportError: 
      e = None #default behaviour 
      self.override_obj = None 

     self.p = p 

    def act(self): 
     if self.override_obj: 
      return self.override_obj.act() 
     else: 
      print 'Default behaviour' 
+0

つまり、インスタンスメソッドではなく、インスタンスへの参照を保持します。その後、必要に応じてメソッドを呼び出します。 –

+0

しかし、これは間違いなく動作しますが、同じオブジェクトの2つのほぼ同じコピーで終わるのです... –

+0

概念的に異なるとしたい場合は、最初にインスタンス化する代わりにファクトリ関数を試すことができます。この関数はインポートを試行し、適切なインスタンスを返すことができます。 –

関連する問題