Kann jemand helfen, diesen Python-Code zu verdichten?

8

Ich schreibe ein Skript in Python und habe ein kleines Problem:

%Vor%

Wie Sie sehen, ist dieser Code entsetzlich überflüssig. Ich habe versucht, es so zu kondensieren:

%Vor%

PyQt4 erwartet jedoch, dass die Klassenmethoden für die Klasse selbst und nicht für eine Instanz vorhanden sind. Das Verschieben des Codes setattr aus dem Block __init__ funktioniert auch nicht, weil self nicht für die Klasse definiert wurde. Daher weiß ich nicht wirklich, was zu tun ist.

Kann jemand einen Weg finden, diesen Code zu verdichten?

    
Blender 12.08.2012, 09:59
quelle

6 Antworten

5

Es gibt viele Möglichkeiten, dies zu tun: Klassen-Dekorator, Metaklasse, Mixin.

Gemeinsame Hilfsfunktion:

%Vor%

Klassen-Dekorator

%Vor% Verwendung %Vor%

Wenn es keine Unterstützung für Klassen-Dekoratoren gibt, könnten Sie versuchen:

%Vor%

Metaklasse

%Vor% Verwendung %Vor%

Hinweis: Sie können dieselbe Metaklasse erneut verwenden, wenn Sie die Liste der Eigenschaften als Klassenattribut festlegen:

%Vor%

Sie könnten auch attrs direkt ändern: attrs[name] = value , bevor Sie type() anstelle von setattr(cls, name, value) aufrufen.

Das oben genannte geht von QObject.__class__ is type aus.

Mischen

%Vor% Verwendung %Vor%

Ich habe nichts davon versucht. Der Code ist hier, um die Menge und die Art des Codes zu zeigen, der zur Implementierung des Features erforderlich sein könnte.

    
jfs 12.08.2012, 12:08
quelle
2

Sie können diese Methoden außerhalb der Klassendefinition hinzufügen:

%Vor%

Der einfachste Weg besteht darin, für jede Eigenschaft eine Schließung zu erstellen, deren __name__ zu überschreiben (nur für den Fall, dass @pyqtProperty sie benötigt) und an die Klasse zu binden:

%Vor%     
Eldar Abusalimov 12.08.2012 11:28
quelle
1

Ich bin mir ziemlich sicher, dass dies funktionieren kann, wenn Sie Ihre Schleife aus der Klasse entfernen und eine Schließung erstellen, die alle Attributnamen enthält:

%Vor%

Ich habe das nicht mit den tatsächlichen QT-basierten Klassen getestet, mit denen Sie es zu tun haben, aber eine einfachere Version mit normalen Python property -Instanzen hat perfekt funktioniert. Ich bin mir auch nicht sicher, ob das eine gute Idee ist, denn es wäre ziemlich schwierig herauszufinden, was vor sich geht, wenn man es nicht schon kennt.

    
Blckknght 12.08.2012 10:56
quelle
1

Ich bin nicht davon überzeugt, dass ich das mag, aber es ist eine mögliche Option, ist nicht zu schwer zu verstehen, und beseitigt die Notwendigkeit für getattr s ... Das Folgende kann ein bisschen wie ein Makro verwendet werden - aber vielleicht müssen Sie etwas optimieren ... (zB nehmen Sie funcs von einer Klassendefinition, die mit get beginnt, oder von einem existierenden Objekt etc ...) Man könnte auch eine replizieren hinzufügen, um zu beschreiben, dass es eine Unterstützung ist Klasse für die Anbindung von Eigenschaften an Benutzerobjekte oder was auch immer ...)

%Vor%

Wenn Sie diese Funktion ausführen, können Sie Ihre Hauptklasse wie folgt schreiben:

%Vor%     
Jon Clements 12.08.2012 11:10
quelle
1

Ich habe die folgende Lösung für Python 3 getestet. Sie verwendet das Schlüsselwort metaclass

%Vor%

Alternativ hätte ich die Einträge für den Klasseneintrag wie folgt erstellen können:

classdict[attribute] = lambda self, attr=attribute: pyqtProperty(QVariant, getattr(self.user, 'get_' + attr))()

aber das ist ein Attr Argument. Mit eval() machen wir dieses Argument zu einem Kern

Wir hätten auch functools.partial verwenden können:

classdict[attribute] = functools.partial(lambda self, attr: pyqtProperty(QVariant, getattr(self.user, 'get_' + attr))(), attr=attribute)

aber dann muss der Aufruf u.method(u) sein. Es kann nicht u.method()

sein

Der Aufruf LightDMUser.method(u) funktioniert mit allen 3 Implementierungen

Grüße

    
Daniel 12.08.2012 15:21
quelle
0

Es ist schwierig, für eine pyqtProperty mit einer Metaklasse oder einem Klassen-Dekorator die Standardwerte zu reduzieren, aber das ist etwas, was wir hier als Ausgangspunkt haben. Der Nachteil ist, dass Sie nicht mehr die @decorator-Syntax verwenden müssen, aber es scheint, als wäre es in dieser Situation wünschenswert, dies in eine einzige Codezeile zu bringen.

Sie können dies so einrichten, dass es zu Ihrem Benutzerobjekt anstatt nur self aufruft, oder Sie könnten ein benutzerdefiniertes getattr Verhalten für LightDMUser implementieren, das automatisch zu self.user aufruft.

%Vor%     
jbee 27.03.2015 01:47
quelle

Tags und Links