Hallo zusammen,
mein Alter, ooh... 54, sorry,
hätte ich schonmal angeben sollen..
Mittlerweile habe ich es nun fertigbekommen.
Danke nochmal an alle Tipp-Geber, ist nun
auf die anständige Weise mittels "Wrapper"
erstellt.
Hat einige Zeit und viel lesen in Anspruch
genommen, aber dann bin ich i-wann bei
lambda: ausgekommen. Auch partial hatte
mich schon zum Ziel gebracht, aber mit
lambda konnte man sich zusätzlichhes import
ersparen und von daher weniger Code zum
Abarbeiten verursachen.
Schönen Tag noch,
Gruß
gu.lux
Probleme mit PyQT, Python und Shell-commands [Anfänger]
- Hyperion
- Moderator
- Beiträge: 7478
- Registriert: Freitag 4. August 2006, 14:56
- Wohnort: Hamburg
- Kontaktdaten:
Sofern Du `lambda` als Mini-Slot-Funktion direkt im Binding von SIGNAL zu SLOT verwendest, sei gewarnt. Iirc kann so etwas zu Problemen führen bei PyQt.. ich meine dazu mal etwas gelesen zu haben. Vielleicht kann lunar da für Aufklärung sorgen?
Also etwa bei Konstrukten wie diesem hier:
Also etwa bei Konstrukten wie diesem hier:
Code: Alles auswählen
self.ui.textfield.textChanged.connect(lambda text: something)
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
assert encoding_kapiert
Im moment sieht es so aus:
in einem Tuppel sind die strings für die funktion buttonhot() hinterlegt. Somit muss ich nur eine funktion
für alle Tasten haben, da je nach gedrückter Taste der passende String abgeliefert wird und dann in einem
String mit dem Rest der Pfadangabe zusammen gesetzt wird. Das Resultat wird dann an os.system()
übergeben und auch so ausführt, wie ich es möchte.
Da ich keine IR-Fernbedienungen nutze, habe ich bisher keine beinträchtingungen erkannt.
Aber danke für den Hinweis, sollte es zu Problemen kommen, werde ich mich gern daran
erinnern.
gruss
gu.lux
Code: Alles auswählen
QtCore.QObject.connect(self.ui.pushButton, QtCore.SIGNAL("clicked()"), lambda: buttonhot(9))
QtCore.QObject.connect(self.ui.pushButton_2, QtCore.SIGNAL("clicked()"), lambda: buttonhot(10))
für alle Tasten haben, da je nach gedrückter Taste der passende String abgeliefert wird und dann in einem
String mit dem Rest der Pfadangabe zusammen gesetzt wird. Das Resultat wird dann an os.system()
übergeben und auch so ausführt, wie ich es möchte.
Da ich keine IR-Fernbedienungen nutze, habe ich bisher keine beinträchtingungen erkannt.
Aber danke für den Hinweis, sollte es zu Problemen kommen, werde ich mich gern daran
erinnern.
gruss
gu.lux
- Hyperion
- Moderator
- Beiträge: 7478
- Registriert: Freitag 4. August 2006, 14:56
- Wohnort: Hamburg
- Kontaktdaten:
Du solltest Dir die neue Semantik von "connect" angewöhnen:
Die ist viel besser zu lesen und zudem zukunftssicherer.
Eigentlich gibt es genau dafür `partial` - der import würde mir da keine Sorgen machen.
Anstelle von `os.system` würde ich Dir zudem das `subprocess`-Modul vorschlagen
Code: Alles auswählen
# alt
QtCore.QObject.connect(self.ui.pushButton, QtCore.SIGNAL("clicked()"), lambda: buttonhot(9))
# neu
self.ui.pushButton.clicked.connect(lambda: buttonhot(9))
Eigentlich gibt es genau dafür `partial` - der import würde mir da keine Sorgen machen.
Anstelle von `os.system` würde ich Dir zudem das `subprocess`-Modul vorschlagen
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
assert encoding_kapiert
Hallo Hyperion,
werde ich sicher probieren, habe mich hierbei jedoch in der Hauptsache an die Doku`s zu PyQt
in den versch. Sprachen gehalten, ebenso wie an entsprechen gefundene Tutorials.
Aber man kann ja immer dazu lernen
Das mit Subprocess hatte ich auch gelesen, war mir aber für mein Gefühl zu viel, da
ich nicht vorhabe, "returns" aus dem Prozess abzufragen oder zu verwerten. Nichts desto
Trotz, werde ich mir auch dazu die Doku nochmal genauer ansehn.
werde ich sicher probieren, habe mich hierbei jedoch in der Hauptsache an die Doku`s zu PyQt
in den versch. Sprachen gehalten, ebenso wie an entsprechen gefundene Tutorials.
Aber man kann ja immer dazu lernen
Das mit Subprocess hatte ich auch gelesen, war mir aber für mein Gefühl zu viel, da
ich nicht vorhabe, "returns" aus dem Prozess abzufragen oder zu verwerten. Nichts desto
Trotz, werde ich mir auch dazu die Doku nochmal genauer ansehn.
- Hyperion
- Moderator
- Beiträge: 7478
- Registriert: Freitag 4. August 2006, 14:56
- Wohnort: Hamburg
- Kontaktdaten:
Dort wird def. die neue Semantik beschriebengurulux hat geschrieben: werde ich sicher probieren, habe mich hierbei jedoch in der Hauptsache an die Doku`s zu PyQt in den versch. Sprachen gehalten,
Das stimmtgurulux hat geschrieben: Aber man kann ja immer dazu lernen
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
assert encoding_kapiert
ich schrieb ja auch "ebenso ... Tutorials", also habe ich immer das verwendet,Hyperion hat geschrieben:Dort wird def. die neue Semantik beschriebengurulux hat geschrieben: werde ich sicher probieren, habe mich hierbei jedoch in der Hauptsache an die Doku`s zu PyQt in den versch. Sprachen gehalten,
was ich eher verstanden habe. Das ist halt das Ding, mit dem Auftrennen
von Aussagen, ändert leider manchmal die Gesamtaussage.
Aber hast schon Recht, und weniger Zeichen zu Tippen sinds in
der Form angewandt, dann auch noch
- Hyperion
- Moderator
- Beiträge: 7478
- Registriert: Freitag 4. August 2006, 14:56
- Wohnort: Hamburg
- Kontaktdaten:
Nö! Ich habe das durchaus gelesen und mir war letztlich auch klar, dass Du das wohl aus einem Tutorial hast (mir ist auch kein gutes, aktuelles für PyQt /PySide bekannt). Ich wollte Dir lediglich noch mal auf die Stelle stoßen, an der die "Referenz" zu finden istgurulux hat geschrieben: ich schrieb ja auch "ebenso ... Tutorials", also habe ich immer das verwendet,
was ich eher verstanden habe. Das ist halt das Ding, mit dem Auftrennen
von Aussagen, ändert leider manchmal die Gesamtaussage.
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
assert encoding_kapiert
@gurulux: Bitte halte Dich nicht an irgendwelche x-beliebigen Tutorials. Du solltest mittlerweile bemerkt haben, dass das keine gute Idee ist. Insbesondere weil es speziell zu PyQt und PySide keine guten gibt.
@Hyperion: "lambda" erzeugt Funktionsabschlüsse (aka Closures), "partial()" nicht:
Beachte den Unterschied zwischen [6] und [12]. Zur detaillierten Erklärung erlaube ich mir, auf eine Antwort auf Stackoverflow zu verweisen.
Das hat jetzt allerdings nichts mit PyQt speziell zu tun, sondern ist eben das allgemeine Verhalten von "lambda". Was natürlich überraschend sein kann, wenn man - wie in der Frage zur verlinkten Antwort - die freien Namen im Funktionsabschluss im zugehörigen Namensraum neu bindet.
[1] Namen also, die nicht in der Parameterliste des "lambda"-Ausdrucks vorkommen.
@Hyperion: "lambda" erzeugt Funktionsabschlüsse (aka Closures), "partial()" nicht:
Code: Alles auswählen
In [1]: i = 10
In [2]: s = 'spam'
In [3]: f = lambda: print(s)
In [4]: f()
spam
In [5]: s = 'eggs'
In [6]: f()
eggs
In [7]: s = 'spam'
In [9]: f = partial(print, s)
In [10]: f()
spam
In [11]: s = 'eggs'
In [12]: f()
spam
Das hat jetzt allerdings nichts mit PyQt speziell zu tun, sondern ist eben das allgemeine Verhalten von "lambda". Was natürlich überraschend sein kann, wenn man - wie in der Frage zur verlinkten Antwort - die freien Namen im Funktionsabschluss im zugehörigen Namensraum neu bindet.
[1] Namen also, die nicht in der Parameterliste des "lambda"-Ausdrucks vorkommen.
- cofi
- Python-Forum Veteran
- Beiträge: 4432
- Registriert: Sonntag 30. März 2008, 04:16
- Wohnort: RGFybXN0YWR0
Kann es sein, dass du ``partial`` und ``lambda`` vertauschst? Nach deinem Trace erzeugt ``lambda`` keine Closure und ``partial`` schon.
Wuerde ``lambda`` eine Closure erzeugen, ergaebe dies keinen ``NameError``:
Wuerde ``lambda`` eine Closure erzeugen, ergaebe dies keinen ``NameError``:
Code: Alles auswählen
In [5]: f = lambda: print(s)
In [6]: f()
foo
In [7]: del s
In [8]: f()
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
/home/cofi/<ipython-input-8-0ec059b9bfe1> in <module>()
----> 1 f()
/home/cofi/<ipython-input-5-fb4c65255a58> in <lambda>()
----> 1 f = lambda: print(s)
NameError: global name 's' is not defined
Michael Markert ❖ PEP 8 Übersetzung ❖ Tutorial Übersetzung (3.x) ⇒ Online-Version (Python 3.3) ❖ Deutscher Python-Insider ❖ Projekte
@cofi: Kann es sein, dass Du "Closure" falsch verstehst? "Closure" bedeutet, dass eine Funktion Namen aus dem umgebenden Namensraum referenziert. "partial" ist keine Closure, sondern eine partielle Funktionsanwendung.
- cofi
- Python-Forum Veteran
- Beiträge: 4432
- Registriert: Sonntag 30. März 2008, 04:16
- Wohnort: RGFybXN0YWR0
Deine Definition verliert den "Abschluss" Teil der "Closure", nämlich, dass die Closure die freien Variablen mit den zur Definitionszeit gebundenen Werten mit sich herum trägt.
Mangels besserer Quelle aus der Wikipedia:
Mangels besserer Quelle aus der Wikipedia:
https://en.wikipedia.org/wiki/Closure_(computer_science) hat geschrieben:Such a function is said to be "closed over" its free variables. The referencing environment binds the nonlocal names to the corresponding variables in scope at the time the closure is created, additionally extending their lifetime to at least as long as the lifetime of the closure itself. When the closure is entered at a later time, possibly from a different scope, the function is executed with its non-local variables referring to the ones captured by the closure.
Michael Markert ❖ PEP 8 Übersetzung ❖ Tutorial Übersetzung (3.x) ⇒ Online-Version (Python 3.3) ❖ Deutscher Python-Insider ❖ Projekte
Imho sind beides Closures*, nur nutzt lunar nicht den Erstellungskontext im lambda-Bsp. sondern referenziert auf eine globalen Bezeichner im Funktionskörper, welcher neu ausgewertet wird und eine anderes Objekt vorfindet.
Mit Bindung an einen lokalen Namen klappts auch mit lambda (ungetestet):Javascript verhält sich da nicht anders und meckert auch innerhalb eines Closures über das Verschwinden globaler Variablen.
* Technisch gesehen, würde ich sagen, ist partial kein Closure, da es kein Funktionsobjekt zurückgibt. Allerdings imitiert das partial-Objekt Closure-Funktionalität. An der Stelle könnte man darüber streiten, ob in einer Sprache, bei der Funktionen Objekte sind, überhaupt echte Closures möglich sind. Zumindest werden zu first-class functions und higher-order functions Tricks mit Funktionspointern oder Objekten in Wikipedia unter Alternativen aufgeführt.
Edit: Ergänzungen eingefügt - war gestern schon spät
Mit Bindung an einen lokalen Namen klappts auch mit lambda (ungetestet):
Code: Alles auswählen
a = 1
f = lambda x=a : x
f() # geht
del a
f() # geht auch
* Technisch gesehen, würde ich sagen, ist partial kein Closure, da es kein Funktionsobjekt zurückgibt. Allerdings imitiert das partial-Objekt Closure-Funktionalität. An der Stelle könnte man darüber streiten, ob in einer Sprache, bei der Funktionen Objekte sind, überhaupt echte Closures möglich sind. Zumindest werden zu first-class functions und higher-order functions Tricks mit Funktionspointern oder Objekten in Wikipedia unter Alternativen aufgeführt.
Edit: Ergänzungen eingefügt - war gestern schon spät
@cofi: Ein Funktionsabschluss bindet eben nicht die zur Definitionszeit vorliegenden Werte freie Variablen. Er bindet die freien Variablen selbst, im Falle von Python eben über die Referenz des übergeordneten Namensraums.
"partial()" ist schon deswegen keine Closure, weil es da überhaupt gar keine freien Variablen gibt. Die an "partial()" übergebenen Objekte werden wie gesagt übergeben, es liegt also ein ganz normaler Funktionsaufruf vor, bei dem die übergebenen Objekte innerhalb der Funktion an unabhängige, lokale und gebundene Variablen gebunden werden. Die Variablen, die im Aufruf von "partial()" stehen, sind im aufrufenden Namensraum gebunden, und gehen mit dessen Bereinigung verloren. Es wird also auch nicht die Lebenszeit dieser Variablen verlängert.
@jerch: In Deinem Beispiel ist "f" kein Funktionsabschluss mehr, da er keine freien Variablen mehr referenziert. "x" ist gebunden im Namensraum von "f", und "a" wird zum Zeitpunkt der Erzeugung von "f" ausgewertet.
"partial()" ist schon deswegen keine Closure, weil es da überhaupt gar keine freien Variablen gibt. Die an "partial()" übergebenen Objekte werden wie gesagt übergeben, es liegt also ein ganz normaler Funktionsaufruf vor, bei dem die übergebenen Objekte innerhalb der Funktion an unabhängige, lokale und gebundene Variablen gebunden werden. Die Variablen, die im Aufruf von "partial()" stehen, sind im aufrufenden Namensraum gebunden, und gehen mit dessen Bereinigung verloren. Es wird also auch nicht die Lebenszeit dieser Variablen verlängert.
@jerch: In Deinem Beispiel ist "f" kein Funktionsabschluss mehr, da er keine freien Variablen mehr referenziert. "x" ist gebunden im Namensraum von "f", und "a" wird zum Zeitpunkt der Erzeugung von "f" ausgewertet.
In der Tat ist mein Bsp. falsch und muss eigentlich so aussehen:lunar hat geschrieben:@jerch: In Deinem Beispiel ist "f" kein Funktionsabschluss mehr, da er keine freien Variablen mehr referenziert. "x" ist gebunden im Namensraum von "f", und "a" wird zum Zeitpunkt der Erzeugung von "f" ausgewertet.
Code: Alles auswählen
lambda a : lambda :a
Code: Alles auswählen
f = lambda: print(s)
Code: Alles auswählen
def f():
return print(s)
Der Trick an Closures ist doch, dass man sich einen "Zwischennamensraum" zunutze macht, um Zustände zu speichern, die bei erneutem Aufruf restauriert werden (und nichtlokal sind, da aus dem Zwischennamensraum), Bsp in Javascript:
Code: Alles auswählen
/*
Beispiel 1
ist zwar ein Closure, doch nutzt a die Closurefunktionalität nicht,
da es nicht Teil des Zwischennamensraumes ist - analog zu `lambda : print(s)`
*/
var a = 1;
function f() {
return function() {return a}
}
g = f();
g(); // --> gibt a zurück
delete a;
g(); //--> Fehler
/*
Beispiel 2
a wird im Zwischennamensraum gebunden und ist daher
auch nach Löschen von a weiter in der inneren Funktion verfügbar
*/
var a = 1;
function f(a) {
return function() {return a}
}
g = f(a);
g(); // --> gibt a zurück
delete a;
g(); //--> geht
@jerch
"Closures are a poor man's objects. And objects are a poor man's closures".
Partial benutzt ein Objekt, und erreicht dadurch die Aufbewahrung des Zustandes. Aber eben *kein* Closure. Wenn du die Begriffe zur Unkenntlichkeit aufweichen willst, wem ist damit geholfen? Das alles ist irgendwie programmieren...
"Closures are a poor man's objects. And objects are a poor man's closures".
Partial benutzt ein Objekt, und erreicht dadurch die Aufbewahrung des Zustandes. Aber eben *kein* Closure. Wenn du die Begriffe zur Unkenntlichkeit aufweichen willst, wem ist damit geholfen? Das alles ist irgendwie programmieren...
@jerch: deets hat bereits festgestellt, dass Du den falschen Schluss aus "Beispiel 2" gezogen hast. Es folgt daraus eben nicht, dass "partial()" "closure-like" ist. Du hast vielmehr gezeigt, dass man mit Funktionsabschlüssen Objektexemplare implementieren kann (und umgekehrt natürlich). Was Du mit "Zwischennamensraum" bezeichnet hast, ist nichts anderes, als der Namensraum eines Objektexemplars (im Falle von Python alle an "self" gebundenen Namen).
"partial()" selbst ist dennoch kein Funktionsabschluss, und dem auch nicht ähnlicher als jedwedes andere Objekt, schon weil das wesentliche konstituierende Element eines Funktionsabschlusses, nämlich das Vorkommen freier Variablen, bei der Verwendung von "partial()" gar nicht gegeben ist. Auch ist dieser "Zwischennamensraum" nicht die eigentliche Funktionalität [1] eines Funktionsabschlusses, sondern nur ein ganz normaler Namensraum, den man halt zusammen mit einem Funktionsabschluss nutzen kann (beispielsweise um Objekte zu implementieren).
Die Funktionalität eines Funktionsabschlusses besteht - nur um das nochmals klarzustellen - ausschließlich in der Bindung freier Variablen in einem Ausdruck an den umgebenden Namensraum. Dass Funktionsabschlüsse benutzt werden können, um Objekte zu implementieren, und diese Konzepte mithin von gleicher Mächtigkeit sind, ist nicht die konstituierende Eigenschaft eines Funktionsabschlusses. Anders gesagt, der Terminus "Funktionsabschluss" wird nicht darüber definiert, dass man damit Objekte implementieren kann. Der Zusammenhang zwischen "partial()" und einem Funktionsabschluss ist also in etwa derselbe wie zwischen zwei Programmiersprachen: Man kann jede Sprache A in jeder anderen Sprache B implementieren (vorausgesetzt, beide sind gleich mächtig), doch trotzdem sind A und B noch immer unterschiedliche Sprachen.
"partial()" selbst ist dennoch kein Funktionsabschluss, und dem auch nicht ähnlicher als jedwedes andere Objekt, schon weil das wesentliche konstituierende Element eines Funktionsabschlusses, nämlich das Vorkommen freier Variablen, bei der Verwendung von "partial()" gar nicht gegeben ist. Auch ist dieser "Zwischennamensraum" nicht die eigentliche Funktionalität [1] eines Funktionsabschlusses, sondern nur ein ganz normaler Namensraum, den man halt zusammen mit einem Funktionsabschluss nutzen kann (beispielsweise um Objekte zu implementieren).
Die Funktionalität eines Funktionsabschlusses besteht - nur um das nochmals klarzustellen - ausschließlich in der Bindung freier Variablen in einem Ausdruck an den umgebenden Namensraum. Dass Funktionsabschlüsse benutzt werden können, um Objekte zu implementieren, und diese Konzepte mithin von gleicher Mächtigkeit sind, ist nicht die konstituierende Eigenschaft eines Funktionsabschlusses. Anders gesagt, der Terminus "Funktionsabschluss" wird nicht darüber definiert, dass man damit Objekte implementieren kann. Der Zusammenhang zwischen "partial()" und einem Funktionsabschluss ist also in etwa derselbe wie zwischen zwei Programmiersprachen: Man kann jede Sprache A in jeder anderen Sprache B implementieren (vorausgesetzt, beide sind gleich mächtig), doch trotzdem sind A und B noch immer unterschiedliche Sprachen.