Ich habe manchmal Code wie den folgenden:
class Example:
def something(self, par):
class MyThread(threading.Thread):
def run(myself):
self.so_something(par)
MyThread().start()
def do_something(self, par):
...
Das sieht relativ umständlich aus. Gibt es sowas wie anonyme Klassen,
sodass ich das ähnlich wie in Java ohne eine Klasse "MyThread" schreiben
kann?
class Example {
void something(final Object par) {
(new Thread() {
public void run() {
do_something(par);
}
}).start();
}
}
Oder wie ist der eleganteste Way Of Python, das Obige zu beschreiben?
Viele Grüße
Ole
> class Example:
> def something(self, par):
> class MyThread(threading.Thread):
> def run(myself):
> self.so_something(par)
> MyThread().start()
>
> def do_something(self, par):
> ...
>
> Das sieht relativ umständlich aus.
Ja. Einfacher wäre (in diesem Spezialfall):
class Example:
def something(self, par):
threading.Thread(target=self.do_something,args=(par,)).start()
def do_something(self, par):
...
> Gibt es sowas wie anonyme Klassen,
> sodass ich das ähnlich wie in Java ohne eine Klasse "MyThread" schreiben
> kann?
Im allgemeinen ließe sich hier durchaus auch was bauen wie
def wrapper(a,b,c):
class Temp(object):
...
....
- was dann zu einem vereinfachten Aufruf führt.
Bei konkreter Aufgabenstellung gerne mehr; zu der Threadinggeschichte
hab ich ja schon oben geschrieben, wie es gescheit geht.
Thomas
> class Example:
> def something(self, par):
> threading.Thread(target=self.do_something,args=(par,)).start()
> def do_something(self, par):
> ...
Wobei - wenn ich mirs recht bedenke, würde ich hier das Threadobjekt
zurückgeben anstatt einfach None.
also:
class Example:
def something(self, par):
t=threading.Thread(target=self.do_something,args=(par,))
t.start()
return t
def do_something(self, par):
...
Thomas
äh, was hab ichn hier angestellt? Einrückung bitte ensprechend anpassen.
*grummel*
Thomas
> Im allgemeinen ließe sich hier durchaus auch was bauen wie
>
> def wrapper(a,b,c):
> class Temp(object):
> ...
> ....
>
> - was dann zu einem vereinfachten Aufruf führt.
Das ist aber nicht wirklich anonym, schließlich hat sie ja einen Namen.
Man könnte aber auch ohne ein Namensbinding eine Klasse erstellen, mit
type():
type('Temp', (object,), {})
Voila! Eine Klasse die als Bezeichner 'Temp' hat (Klassen müssen
irgendeinen Beziechner haben), von object erbt und ein leeres Dict hat.
Wenn man jetzt etwas sinnvolles damit machen will, schreibt man
üblicherweise noch etwas in das Dict rein :)
grüße,
Marek
On Tue, 2009-09-29 at 14:34 +0200, Ole Streicher wrote:
> class Example:
> def something(self, par):
> class MyThread(threading.Thread):
> def run(myself):
> self.so_something(par)
> MyThread().start()
>
> def do_something(self, par):
> ...
Es mag einem zwar sinnlos vorkommen, einer solchen Wegwerfklasse
explizit einen Namen geben zu müssen und diesen Namen dann im nächsten
Schritt zu referenzieren. Ich finde dieses Beispiel aber sehr viel
leserlicher als das Java-Pendant. Schon allein, weil die vielen Klammern
wegfallen und alles was zusammen gehört eben wirklich auf einer Ebene
steht.
Mit freundlichen Grüßen,
Dennis Schulmeister
--
Volle Kontaktdaten auf WikiBerd: (http://ncc-1701a.homelinux.net)
Complete contact data on WikiBerd: (http://ncc-1701a.homelinux.net)
http://www.denchris.de - http://www.motagator.net/bands/65
<GnuPG KeyIDs: B8382C97, 01AD62DE>
Nicht nur das, ich finde es allgemein schwer verstaendlich, insbesondere die
Unterscheidung 'self' und 'myself' verletzt das KISS-Prinzip.
> Gibt es sowas wie anonyme Klassen, sodass ich das �hnlich wie in Java ohne
> eine Klasse "MyThread" schreiben kann?
Nein, nicht wirklich. Was Du jedoch machen kannst ist Attribute eines
Objektes verbiegen, wie z.B. das 'run'-Attribut eines 'Thread'-Objekts,
siehe unten.
Was Du speziell bei Threads machen kannst ist das 'thread'-Modul anstatt des
'threading'-Moduls zu verwenden. Dort gibt es eine Funktion namens
'start_new_thread' welche eine Funktion und ein Tupel mit Argumenten nimmt
und als entsprechenden Thread startet.
Leider gibt es das gleiche nicht auch fuer das eigentlich bessere
'threading'-Modul, ausser man macht es selbst:
def start_thread(thread_function, arguments):
thread = Thread()
def run_proxy():
thread_function(arguments)
# redirect 'run' attribute
thread.run = run_proxy
thread.start()
return thread
Dein Code saehe dann so aus:
class Example:
def something(self, par):
start_thread(self.do_something, par)
def do_something(self, par):
...
Uli
def test():
print "hello world"
import threading
t = threading.Thread(group=None, target=test, name="test", args=(),
kwargs=None, verbose=None)
t.start()
Das thread-Modul wird ja nicht mehr zur Verwendung empfohlen...
Gru�,
Dietmar
Ulrich Eckhardt <doom...@knuut.de> writes:
> Ole Streicher wrote:
>> def something(self, par):
>> class MyThread(threading.Thread):
>> def run(myself):
>> self.so_something(par)
> die Unterscheidung 'self' und 'myself' verletzt das KISS-Prinzip.
Wie unterscheidet man denn sonst in einer inneren Klasse zwischen
innerem und äußerem Objekt?
> Was Du jedoch machen kannst ist Attribute eines Objektes verbiegen,
> wie z.B. das 'run'-Attribut eines 'Thread'-Objekts, siehe unten.
Das Verbiegen von Funktionen erscheint mir längerfristig schwerer
wartbar, da man das Verhalten eines Objektes (hier "thread") verändert.
Viele Grüße
Ole
>> die Unterscheidung 'self' und 'myself' verletzt das KISS-Prinzip.
>
> Wie unterscheidet man denn sonst in einer inneren Klasse zwischen
> innerem und äußerem Objekt?
Zum Beispiel kann man dem inneren das äußere "self" als "parent" oder
"other" übergeben oder eine "äußere" Variable anlegen:
def something(self, par):
other=self # eine Möglichkeit
class MyThread(threading.Thread):
other=self # eine weitere
def run(self):
other.do_something(par)
# bzw. self.other.do_something(par)
Aber wie gesagt - das sind an der Stelle alles eher theoretische
Überlegungen, denn Dein ursprungsproblem ist ja gelöst (Parameter
target=,args= und kwargs= bei Initialisierung des Threadobjektes).
Thomas
Oder kuerzer:
t = threading.Thread(target=test)
t.start()
...was mir allerdings eigentlich immer noch eine Zeile zuviel ist. ;)
Auf jeden Fall Danke fuer den Hinweis, diese alternative Aufrufmethode war
mir neu!
Uli
Sorry, hab' keine wirkliche Alternative. Eventuell eine Unterscheidung
zwischen 'inner_self' und 'outer_self', damit es gleich ins Auge sticht.
>> Was Du jedoch machen kannst ist Attribute eines Objektes verbiegen,
>> wie z.B. das 'run'-Attribut eines 'Thread'-Objekts, siehe unten.
>
> Das Verbiegen von Funktionen erscheint mir l�ngerfristig schwerer
> wartbar, da man das Verhalten eines Objektes (hier "thread") ver�ndert.
Ja und nein. Das Verhalten ist dass 'run' aufgerufen wird, und daran aendert
sich nix. Die Variante die die Funktion als 'target' dem Konstruktor zu
uebergeben mach (vermutlich) genau das gleiche. Ansonsten kann man
natuerlich viel Schaden mit solchen Sachen anrichten, es kommt halt auf's
Mass an.
Gruss!
Uli
threading.Thread(target=test).start()
Gru�,
Dietmar
> Oder kuerzer:
>
> t = threading.Thread(target=test)
> t.start()
>
> ...was mir allerdings eigentlich immer noch eine Zeile zuviel ist. ;)
Tja, leider geben die meisten Methoden, die etwas auf ein Objekt
anwenden und "kein Ergebnis haben", None zurück an Stelle des Objekts.
Ist blöd, wenn man das Objekt dann braucht...
Ein Workaround, falls man so was öfter hat in einem Projekt:
def do_call(obj,func):
func(obj)
return obj
bzw.
do_call=lambda obj,func: (func(obj),obj)[-1]
und dann
return do_call(threading.Thread(target=test), lambda t:t.start())
Oder einfacher:
def starter(obj):
obj.start()
return obj
oder
starter=lambda obj:(obj.start(),obj)[-1]
und
return starter(threading.Thread(target=test))
Man könnte das nun auf die Spitze treiben und schreiben
return (lambda obj:(obj.start(),obj)[-1])(threading.Thread(target=test))
Schöner Einzeiler, aber leider völlig unlesbar. Dann kann ich auch
gleich Perl programmieren.
Dann doch lieber die Variante mit der Zwischenvariable t.
Thomas
Thomas Rachel <nutznetz-drei-...@spamschutz.glglgl.net>
writes:
> Ole Streicher schrieb:
>>> die Unterscheidung 'self' und 'myself' verletzt das KISS-Prinzip.
>> Wie unterscheidet man denn sonst in einer inneren Klasse zwischen
>> innerem und äußerem Objekt?
> Zum Beispiel kann man dem inneren das äußere "self" als "parent" oder
> "other" übergeben oder eine "äußere" Variable anlegen:
Was ist der Vorteil davon? "self" ist doch kein reserviertes Wort,
sondern ein im Grunde beliebiger Name, der nur per Konvention so heißt.
Was spricht dagegen, den anders zu nennen, wenn sich eine Notwendigkeit
dazu ergibt? OK, "myself" würde ich ihn natürlich normalerweise nicht
nennen, aber z.B. MyThread_self, oder inner_self.
Innere Klassen sind ja im Allgemeinen kurz, sodass man die verschiedene
Verwendung von "self" und "xyz_self" ohne weiteres überblicken sollte.
Dafür extra eine eigene Variable einzuführen, erscheint mir deutlich
komplizierter zu sein.
> Aber wie gesagt - das sind an der Stelle alles eher theoretische
> Überlegungen, denn Dein ursprungsproblem ist ja gelöst
Mir geht es hier ja i.allg. weniger um die Behandlung des konkreten
Problems als vielmehr darum, die "Python-Denkweise" zu verstehen.
Viele Grüße
Ole
> Oder kuerzer:
>
> t = threading.Thread(target=test)
> t.start()
>
> ...was mir allerdings eigentlich immer noch eine Zeile zuviel ist. ;)
Was genau spricht gegen
threading.Thread(target=test).start()
wenn Du t sowieso nicht auf None �berpr�fst?
Gru�, Mark
't' kann nie 'None' werden, ich zumindest wuerde eine Exception erwarten.
Ansonsten, vergleich mal mit
t = threading.start_new_thread(target=test)
Ich finde diese Zeile einfach wesentlich einfacher zu verstehen, weil sie
ohne Umwege genau das beschreibt was ablaufen soll. Leider hat das alte
'thread'-Modul diese Funktion, nich aber das neue 'threading'-Modul.
Uli
> Was genau spricht gegen
>
> threading.Thread(target=test).start()
>
> wenn Du t sowieso nicht auf None überprüfst?
sollte man weshalb genau tun?
Was dagegen spricht, ist, daß man hinterher das Objekt nicht mehr hat,
um es evtl. zu speichern oder zurückzugeben.
Thomas
>> Was genau spricht gegen
>>
>> threading.Thread(target=test).start()
>>
>> wenn Du t sowieso nicht auf None überprüfst?
>
> [...]
>
> Ansonsten, vergleich mal mit
>
> t = threading.start_new_thread(target=test)
>
> Ich finde diese Zeile einfach wesentlich einfacher zu verstehen, weil sie
> ohne Umwege genau das beschreibt was ablaufen soll. Leider hat das alte
> 'thread'-Modul diese Funktion, nich aber das neue 'threading'-Modul.
AFAIR (bin grad zu faul, nachzulesen) ist aber die Verwendung von
threading empfohlen.
Und einen Thread zu erstellen, und ihn dann zu starten, ist IMHO
hinreichend verständlich.
Thomas
> > Was genau spricht gegen
> >
> > threading.Thread(target=test).start()
> >
> > wenn Du t sowieso nicht auf None �berpr�fst?
>
> sollte man weshalb genau tun?
>
> Was dagegen spricht, ist, da� man hinterher das Objekt nicht mehr hat,
> um es evtl. zu speichern oder zur�ckzugeben.
Ja, aber ehrlich gesagt hat er nicht self.t benutzt und die Methode
(zumindest im Beispiel) war danach zu Ende. DANN (also, wenn man 't'
nicht weiter benutzt) kann man eben doch einfach alles in eine Zeile
schreiben, wenn man sich an zwei Zeilen st�rt.
Mehr wollte ich gar nicht sagen - hab aber mit Verweis auf die "None"
Pr�fung irgendwelche Gedanken angesto�en, die ich gar nicht provozieren
wollte ;-)
Gru�, Mark