Wie bekomme ich mich selbst in eine Python-Methode, ohne sie explizit zu akzeptieren?

8

Ich entwickle ein Dokumentations-Test-Framework - im Grunde Unit-Tests für PDFs. Tests sind (dekorierte) Methoden von Instanzen von Klassen, die vom Framework definiert werden. Diese werden zur Laufzeit lokalisiert und instanziiert und die Methoden werden aufgerufen, um die Tests auszuführen.

Mein Ziel ist es, die Menge der schrulligen Python-Syntax zu reduzieren, die die Leute, die Tests schreiben, beachten müssen, da diese Leute Python-Programmierer oder sogar sehr viele Programmierer sein können. Daher möchte ich, dass sie "def foo ():" anstelle von "def foo (self):" für Methoden schreiben können, aber trotzdem "self" verwenden können, um auf Mitglieder zuzugreifen.

In einem normalen Programm würde ich das für eine schreckliche Idee halten, aber in einem domänenspezifischen Sprachprogramm wie diesem scheint es einen Versuch wert.

Ich habe das Selbst erfolgreich aus der Methodensignatur eliminiert, indem ich einen Decorator verwendet habe (tatsächlich, da ich bereits einen Decorator für die Testfälle verwende, würde ich ihn einfach in diesen einfügen), aber "self" bezieht sich dann nicht darauf alles in der Testfallmethode.

Ich habe überlegt, ein Global für sich selbst zu verwenden und sogar eine Implementierung zu entwickeln, die mehr oder weniger funktioniert, aber ich würde eher den kleinsten Namensraum verschmutzen, weshalb ich es vorziehen würde, die Variable direkt in den Test zu injizieren Der lokale Namespace der Fallmethode. Irgendwelche Gedanken?

    
kindall 10.08.2010, 22:28
quelle

5 Antworten

4

Hier ist ein Ein-Linien-Methoden-Dekorator, der die Aufgabe zu erledigen scheint, ohne Spezielle Attribute von Callable types * als schreibgeschützt markiert :

%Vor%

Beachten Sie, dass, wenn Sie keine Vorkehrungen treffen, um dies zu verhindern, ein Nebeneffekt von Die Funktion eval() kann darin bestehen, dass einige Einträge - wie zB ein Verweis auf das Modul __builtin__ unter dem Schlüssel __builtins__ - automatisch an den übergebenen dict angefügt werden.

@kendall: Nach Ihrem Kommentar, wie Sie dies mit Methoden in Container-Klassen verwenden (aber die Injektion zusätzlicher Variablen für den Moment ignorieren) - ist das folgende etwas wie das, was Sie tun? Es ist schwierig für mich zu verstehen, wie die Dinge zwischen dem Framework und dem, was die Benutzer schreiben, aufgeteilt sind. Es klingt wie ein interessantes Designmuster für mich.

%Vor%     
martineau 11.11.2010, 00:22
quelle
5

Meine angenommene Antwort auf diese Frage war ziemlich dumm, aber ich fing gerade erst an. Hier ist ein viel besserer Weg. Dies wird nur spärlich getestet, aber es ist gut für eine Demonstration der richtigen Art und Weise, dies zu tun, was unpassend ist. Es funktioniert sicher auf 2.6.5. Ich habe keine anderen Versionen getestet, aber keine Opcodes sind fest codiert, also sollte es ungefähr so ​​tragbar sein wie die meisten anderen 2.x-Codes.

add_self kann als Dekorator angewendet werden, aber das würde den Zweck zunichte machen (warum nicht einfach 'self' eingeben?) Es wäre leicht, die Metaklasse von meiner anderen Antwort anzupassen, um stattdessen diese Funktion anzuwenden.

%Vor%     
aaronasterling 10.08.2010 22:42
quelle
4

kleines Upgrade für aaronasterling's Lösung (ich habe nicht genug Reputation um es zu kommentieren):

%Vor%

Aber beide Lösungen funktionieren unvorhersehbar, wenn f function rekursiv für verschiedene Instanzen aufgerufen wird, also müssen Sie es so klonen:

%Vor%     
Odomontois 11.08.2010 01:28
quelle
3

Der Trick besteht darin, 'self' zu f.func_globals hinzuzufügen. Dies funktioniert in python2.6. Ich sollte wirklich dazu übergehen, andere Versionen zu installieren, um so etwas zu testen. Entschuldigung für die Codewand, aber ich beziehe mich auf zwei Fälle: mit einer Metaklasse und mit einem Dekorateur. Für Ihren Anwendungsfall denke ich, dass die Metaklasse besser ist, da der ganze Sinn dieser Übung darin besteht, Benutzer vor Syntax zu schützen.

%Vor%     
aaronasterling 11.08.2010 00:32
quelle
2

Dies könnte ein Anwendungsfall für Dekorateure sein - Sie geben ihnen eine kleine Menge Lego Bausteine, mit denen man Funktionen aufbauen kann, und das komplizierte Framework-Zeug wird über @testcase oder sowasuch eingefügt.

Bearbeiten: Sie haben keinen Code gepostet, also wird dies skizzenhaft sein, aber sie müssen keine Methoden schreiben. Sie können normale Funktionen ohne "Selbst" schreiben, und Sie könnten Dekoratoren wie in diesem Beispiel aus dem Artikel verwenden, den ich verlinkt habe:

%Vor%     
chryss 10.08.2010 22:39
quelle

Tags und Links