2016-06-10 5 views
1

Ich versuche, eine wiederholte Funktionalität in Klassen (einschließlich ihrer Initialisierer) und Methoden in einer effizienten und pythonischen Weise zu implementieren.Wiederholte Funktionalität/Code in Python-Klassen, Initialisierer und Methoden

Ich Unterklassen und überschreiben Methoden (wie gesehen here). Ich habe Zähler für jede Klasse definiert und ergänzt.

Mein Code

class StructuralAnalysis(object): 
    def __init__(self): 
     self.counter_results = [] # probably a dict would be better 

    def generate_structural_metrics(self): 
     # declare counters 
     cnum = 0 
     cstr = 0 
     cbytes = 0 
     ... 
     ... 
     ... 

     for node in ast.walk(self.tree): 
      if isinstance(node, ast.Num): 
       cnum += 1 
      elif isinstance(node, ast.Str): 
       cstr += 1 
      elif isinstance(node, ast.Bytes): 
       cbytes += 1 
      elif ... 
      elif ... 
      elif ... 

      self.counter_results = [cnum, cstr, cbytes, .......] 
      # some counters may require some further calculations 

      return self.counter_results 

Meine Frage ist, ob die oben in einer Pythonic und/oder effiziente Art und Weise umgesetzt werden könnte; wie eine andere Klassenmethode für jeden Zähler zu haben, die jede überschriebene Methode aufrufen wird, um die erweiterte Zuweisung durchzuführen? Dies um eine - möglicherweise - große Anzahl von Zählerdeklarationen und wiederholten Code zu vermeiden. Irgendwelche Vorschläge wären großartig.

+0

suchen Sie für Meta-Programmierung in Python? – biobirdman

+0

@biobirdman keine Ahnung, was das ist. Ich erkunde nur die besten Ansätze für die implementierte wiederholte Funktionalität in Klassen. –

Antwort

1

Ich würde nicht eine Menge von Klassen verwenden, da der Overhead wahrscheinlich zu groß ist (unter der Annahme, dass die meisten nur einen einzigen Zähler für diesen Ast-Typ behalten).

Ich würde jedoch prüfen, ob es eine Möglichkeit gibt, den ast-Typ über eine Funktion zu erhalten (also nicht boolesch für isinstance, sondern type (var). Wenn Sie den ast-Typ haben, können Sie das Wörterbuch verwenden, das Sie bereits hatten) . als Idee Das ist etwas wie

counters = {} 
for node in ast.walk(self.tree): 
    counters[type(node)] += 1 

zu schreiben, wird durch alle Knoten durchlaufen und die Zähler in einem Wörterbuch hinzufügen

Für die weiteren Berechnungen können Sie ein anderes Wörterbuch machen:

counter_calculations = {} 

counter_calculations[ast.BYTE] = perform_additional_calculations_byte 

Fügen Sie für jeden Typ die Funktionsreferenz hinzu, wenn eine Funktion benötigt wird. Auf diese Weise können Sie sehr einfach die zusätzlichen Berechnungen aufrufen, die für einen Typ erforderlich sind (Sie können ihn im selben Iterator verwenden).

if (type(node) in counter_calculations: 
    counter_calculations[type(node)]() 

dann die verschiedenen Funktionen implementieren, zum Beispiel für ein Byte:

def perform_additional_calculations_byte(byte_node): 
    ... some calculations 

Für die Zählergebnisse Sie zurückkommen können die Zähler Wörterbuch zurückzukehren.

+0

Ich habe Schwierigkeiten zu verstehen, was Sie vorschlagen (Anfänger in Python). Könnten Sie sich bitte ein paar Minuten Zeit nehmen, um das, was Sie sagen, in den kleinen Code-Block zu implementieren, den ich in meine Beschreibung als Beispiel einfüge? –

+0

All Ihren Code habe ich angepasst, was ich denke, ist die Lösung, die Sie suchen (oder vermisse ich einen Code Chunk?) –

+0

Ich habe verstanden, was Sie vorschlagen. Sehr schlau. Allerdings muss ich für diesen speziellen Fall alle 'isinstance'-Prüfungen durchführen, also denke ich, dass dies keine ideale Lösung für mich ist. Ich werde Ihre Antwort akzeptieren, wenn keine weiteren Vorschläge vorliegen. –

Verwandte Themen