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?
Es gibt viele Möglichkeiten, dies zu tun: Klassen-Dekorator, Metaklasse, Mixin.
Gemeinsame Hilfsfunktion:
%Vor%Wenn es keine Unterstützung für Klassen-Dekoratoren gibt, könnten Sie versuchen:
%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.
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.
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:
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.
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 ...)
Wenn Sie diese Funktion ausführen, können Sie Ihre Hauptklasse wie folgt schreiben:
%Vor%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()
Der Aufruf LightDMUser.method(u)
funktioniert mit allen 3 Implementierungen
Grüße
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%