2017-12-21 7 views
0

一連の文字列から、クラス内のメソッドを呼び出そうとしています。 残念ながら、このメソッドはクラスの内部であることを示すためにselfが必要なため、正しく呼び出されません。どうすればその論理を修正できますか?一連の文字列からクラス内のメソッドを呼び出す

class SomeClass(object): 
    def apply(self): 
     rules = [{'action': 'replace'}, {'action': 'split'}, {'action': 'remove'}] 
     return [eval('_perform_' + r['action'])() for r in rules 
       if r['action'] in ['replace', 'split', 'remove']] 

    def _perform_replace(self): 
     print("performing replace") 

    def _perform_split(self): 
     print("performing split") 

    def _perform_remove(self): 
     print("performing remove") 

SomeClass().apply() 

これは、次の例外がスローされます。

NameError: name '_perform_replace' is not defined

+0

'staticmethods'にアクセスするには、クラスを静的メンバー関数として定義するために' decorater'を使う必要があります。そして '()'を除いて 'SomeClass.apply()'のように呼びます。さらに、Pythonで文字列を分割/エスケープしようとすると、あなたがしようとしているものよりはるかに簡単な方法があります。 – user1767754

+0

詳しいことはありますか?私は単純な方法があることを知っていますが、ここで私の 'rules'リストは実際にいくつかのドメイン特有の規則を持つjsonファイルです。 - 置き換え/分割/削除はより関与しており、パンダのデータフレームとのやりとりが必要です。私は自分の問題の核心に集中するように説明しなかった。 – Michael

+1

getattrを使用してオブジェクトの属性のようなメソッドにアクセスできます。あなたのapplyメソッドの中から 'getattr(self、 '_perform_' + r ['action'])()' – antonagestam

答えて

3

あなたはインスタンスメソッドを呼び出すためにselfを使用する必要があります。だから、

def apply(self): 
     rules = [{'action': 'replace'}, {'action': 'split'}, {'action': 'remove'}] 
     return [eval('self._perform_' + r['action'])() for r in rules 
       if r['action'] in ['replace', 'split', 'remove']] 

にごapply機能を変更:evalを使用すると、悪い習慣です。理由を見つけることができますhere

代わりにgetattrを使用することができます。たとえばについては

(この例では、ちょうど働いているかgetattr説明することです)

class SomeClass(object): 
    def apply(self): 
     method_to_be_called = "_perform_replace" 
     SomeClass.method_caller(method_to_be_called)(self) 
     # Invoke like this if you want your function to accept args. 
     # SomeClass.method_caller(method_to_be_called, args1, args2,...)(self) 

    def _perform_replace(self): 
     print("performing replace") 

    def _perform_split(self): 
     print("performing split") 

    def _perform_remove(self): 
     print("performing remove") 

    @staticmethod 
    def method_caller(name_, *args, **kwargs): 
     def caller(obj): 
      return getattr(obj, name_)(*args, **kwargs) 

     return caller 
+0

ありがとう、私の例では危険性の低い「eval」の代替案を提案できますか? – Michael

+0

@Michael私の答えの更新を見つけてください。 –

+0

'apply'が' _perform'メソッドにパラメータを渡す必要がある場合、これらのパラメータはそういう形で渡されますか? 'SomeClass.method_caller(method_to_be_called)(self、a、b)' – Michael

0

あなたの例は少し複雑ですが、あなたは、いくつかのロジックに基づいて関数を呼び出したい場合は、あなただけ使用することができますポインタのような関数。

class SomeClass(object): 
    @staticmethod 
    def apply(): 
     rules = [{'action':SomeClass.test()}] 
     return rules[0]['action'] 

    @staticmethod 
    def test(): 
     print("test") 


SomeClass.apply() 
>test 

私はあなたがstaticmethodsに精通しているが、あなたの関数が自分で住むことができるならば、あなたはどこからでも呼び出すことが静的であるためにあなたの機能をdecorateことができるかどうかはわからない。ここでは一例です。

関連する問題