2017-12-21 2 views
0

Aus einer Reihe von Zeichenfolge, ich versuche Methoden innerhalb einer Klasse aufzurufen. Leider wird die Methode nicht ordnungsgemäß aufgerufen, da sie das self benötigt, um anzugeben, dass es in der Klasse intern ist. Wie kann ich diese Logik reparieren?Aufruf Methoden innerhalb einer Klasse aus einer Reihe von Zeichenfolge

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() 

Dies wirft Ausnahme folgende:

NameError: name '_perform_replace' is not defined

+0

Wenn Sie auf 'staticmethods' zugreifen möchten, müssen Sie einen' decorater' verwenden, um die Klasse als statische Elementfunktion zu definieren. Dann nennst du es wie 'SomeClass.apply()' ohne die '()'. Wenn Sie versuchen, Strings in Python zu trennen/zu entkommen, gibt es viel einfachere Möglichkeiten als das, was Sie tun möchten. – user1767754

+0

Könnten Sie das näher erläutern? Ich weiß, dass es einfache Methoden gibt, aber hier ist meine "Regeln" -Liste eigentlich eine JSON-Datei mit mehreren domänenspezifischen Regeln. - Die Ersetzung/Aufteilung/Entfernung sind komplizierter und erfordern Interaktionen mit Pandas Datenrahmen. Ich habe das nicht erklärt, um mich auf den Kern meines Problems zu konzentrieren. – Michael

+1

Sie können mit getattr auf die Methoden wie Attribute des Objekts zugreifen. Also von innerhalb Ihrer Anwendung Methode könnten Sie 'getattr verwenden (selbst, '_perform_' + r ['Aktion'])()' – antonagestam

Antwort

3

Sie self verwenden sollten die Instanzmethoden aufzurufen. So ändern Sie Ihre apply Funktion

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']] 

Hinweis: eval Verwendung eine schlechte Praxis ist. Sie können den Grund finden here

Sie können stattdessen getattr verwenden.

Zum Beispiel (in diesem Beispiel ist nur zu zeigen, wie getattr arbeitet)

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

Danke dafür, könnten Sie eine Alternative zu 'eval' vorschlagen, die für mein Beispiel weniger riskant ist? – Michael

+0

@Michael Bitte finden Sie das Update zu meiner Antwort. –

+0

Danke, wenn 'apply' Parameter an die' _perform' Methoden übergeben muss - diese Parameter werden so übergeben? 'SomeClass.method_caller (method_to_be_called) (self, a, b)' – Michael

0

Ihr Beispiel ein wenig beteiligt ist, aber wenn Sie Funktionen aufrufen möchten, basierend auf einem gewissen Logik, können Sie einfach verwenden die Funktion wie ein Zeiger. Hier ein Beispiel:

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

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


SomeClass.apply() 
>test 

Ich bin nicht sicher, wenn Sie sind vertraut mit staticmethods aber wenn Ihre Funktionen in ihrem eigenen leben können, können Sie Ihre Funktionen decorate statisch zu sein, sie zu nennen von überall.

Verwandte Themen