Additionsproblem

Python und das Qt-Toolkit, erstellen von GUIs mittels des Qt-Designers.
Antworten
mr.mc.mauser
User
Beiträge: 25
Registriert: Sonntag 4. September 2005, 01:18

Hallo,

ich habe ein kleies Addtionsproblem unter pyqt, ich würde gerne in einen Script ein + und ein + Button verwenden, dazu habe ich hier ein kleines demo script erstellt.

Code: Alles auswählen

#!/usr/bin/env python

import sys
from PyQt4 import QtCore, QtGui
X = 0

class MyWidget(QtGui.QWidget):
    def __init__(self, parent=None):
        QtGui.QWidget.__init__(self, parent)
        plus = QtGui.QPushButton("Plus")
        plus.setFont(QtGui.QFont("Times", 18, QtGui.QFont.Bold))
        self.connect(plus, QtCore.SIGNAL("clicked()"),self.aktion)
        layout = QtGui.QVBoxLayout()
        layout.addWidget(plus)
        self.setLayout(layout)

    def aktion(self):
        X += 1
        print X

if __name__ == '__main__':
    app = QtGui.QApplication(sys.argv)
    widget = MyWidget()
    widget.show()
    sys.exit(app.exec_())
Mein Problem ist die Zeile X += 1 diese wird mir immer als Fehler ausgegeben, wie muss ich hier vorgehen ?
Ich möchte eine Startzahl haben (in diesem Beispiel X=5) und beim klick auf Plus soll X=6 sein beim weiteren klick X=7 usw...

Wäre Prima wenn jemand mir helfen könnte.

Gruß
mc.mauser
lunar

Meinst Du nicht auch, dass auch der genaue Text der Fehlermeldung interessant wäre? In diesem Fall ist der Fehler zwar offensichtlich, aber das muss ja nicht so bleiben :)

Dein Fehler ist, dass "X" in der Methode "aktion" nicht existiert. Python unterscheidet zwischen Namen auf Modulebene "X = 0" und Namen in Klassen, Methoden und Funktionen.

Die Lösung ist, ein Exemplarattribut zu verwenden. Das "X = 0" in Zeile fünf ist zu löschen, dafür muss in "__init__()" ein "self.X = 0" stehen, und in "aktion()" muss es "self.X += 1" und "print self.X" heißen.

Falls Dir das nicht unmittelbar klar ist, dann lese Dir bitte im Tutorial den Abschnitt über Klassen durch. Deren Verständnis ist nämlich essentiell für gute GUI-Programme.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

mr.mc.mauser hat geschrieben: Mein Problem ist die Zeile X += 1 diese wird mir immer als Fehler ausgegeben, wie muss ich hier vorgehen ?
Lass mich raten, Du bekommst einen NameError? (Eine Fehlermeldung wäre ja schön gewesen!)
Ich möchte eine Startzahl haben (in diesem Beispiel X=5) und beim klick auf Plus soll X=6 sein beim weiteren klick X=7 usw...
Ich würde X niemals groß schreiben! Widerspricht auch PEP8 iirc.
Zu Deinem Problem:
Du solltest Dir noch einmal den Abschnitt über Klassen im Python Tutorial angucken (was Du ja sicherlich schon einmal getan hast ;-) )

Damit wird das ganze trivial zu beantworten sein!

Mein Rat: Vergiss OOP erst einmal und auch GUIs und erlerne die Grundlagen von Python!
franzf
User
Beiträge: 78
Registriert: Samstag 29. August 2009, 10:21

Hyperion hat geschrieben:Lass mich raten, Du bekommst einen NameError?
Nein, es ist ein UnboundLocalError ;)

google -> "python globale variable"
-> http://openbook.galileocomputing.de/pyt ... 10_003.htm
->

Code: Alles auswählen

def aktion(self):
    global X
    X += 1 
    print X
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

franzf hat geschrieben:
Hyperion hat geschrieben:Lass mich raten, Du bekommst einen NameError?
Nein, es ist ein UnboundLocalError ;)
Ja, ich hatte das "X" auf Modul Ebene nicht gesehen, da ich nur auf die Klasse geguckt hatte ;-)
google -> "python globale variable"
-> http://openbook.galileocomputing.de/pyt ... 10_003.htm
->

Code: Alles auswählen

def aktion(self):
    global X
    X += 1 
    print X
Aber das ist hier jetzt nicht Dein Ernst als Tipp, oder?
lunar

@Hyperion: Das X auf Modulebene hat schlicht gar nichts damit zu tun. Auch ohne diese Zuweisung wird UnboundLocalError ausgelöst. Der Unterschied zwischen NameError und UnboundLocalError liegt in der Zuweisung.
franzf
User
Beiträge: 78
Registriert: Samstag 29. August 2009, 10:21

Hyperion hat geschrieben:
google -> "python globale variable"
-> http://openbook.galileocomputing.de/pyt ... 10_003.htm
->

Code: Alles auswählen

def aktion(self):
    global X
    X += 1 
    print X
Aber das ist hier jetzt nicht Dein Ernst als Tipp, oder?
Ich darf doch annehmen, dass er weiß dass er X als globale Variable definiert, die dann nicht objektgebunden ist. Wahrscheinlich wollte er es nicht, aber ist ja wurscht ;)
lunar

@franzf: Der obligatorische Hinweis, dass global in diesem Fall keine gute Lösung ist, hättest Du im Interesse des OP aber schon noch niederschreiben können :) Schließlich ist ja ziemlich offensichtlich, dass der OP nicht so genau weiß, was er tut.
mr.mc.mauser
User
Beiträge: 25
Registriert: Sonntag 4. September 2005, 01:18

Danke euch allen,

ich werde das nächste mal eine Fehlermeldung mit Posten !!
zu dem Problem kam es übrigens weil vorher da stand

Code: Alles auswählen

    def aktion(self):
        print X
und das hatte geklappt !!
also hatte ich mir überlegt das wenn X angezeigt wird, dann kannst du es ja auch benutzen, gut war nicht so.

Mir ist sehr wohl bewusst das man Variablen oder Objekte nicht X nennt, aber ich wollte halt auf die schnelle ein Skript machen was mein Problem darstellt.

Das mit dem global X ist eigentlich genau das was ich wissen wollte.
vielen vielen Dank.

Übrigens habe ich schon 2 Bücher über Python gelesen, nur manchmal sieht man den Wald vor lauter Bäumen eben nicht mehr, zumal ja wie oben beschrieben die Ausgabe von X funktioniert hat.

Nochmals vielen vielen Dank

Gruß
mc.mauser
lunar

@mr.mc.mauser: Nein, "global" ist nicht das, was Du gesucht hast. Vergiss am besten, dass es dieses Schlüsselwort überhaupt gibt. Von wenigen Ausnahmen abgesehen ist seine Verwendung ein Zeichen mangelnder Qualität.

Die richtige und sinnvolle Lösung habe ich Dir genannt.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

lunar hat geschrieben:@Hyperion: Das X auf Modulebene hat schlicht gar nichts damit zu tun. Auch ohne diese Zuweisung wird UnboundLocalError ausgelöst. Der Unterschied zwischen NameError und UnboundLocalError liegt in der Zuweisung.
Guter Hinweis, da war ich beim Testen zu "faul":

Code: Alles auswählen

In [6]: x += 1
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)

C:\Dokumente und Einstellungen\MECL User 1\<ipython console> in <module>()

NameError: name 'x' is not defined
Dabei entsprach die Situation diesem hier:

Code: Alles auswählen

In [7]: def foo():
   ...:     x += 1
   ...:
   ...:

In [8]: foo()
---------------------------------------------------------------------------
UnboundLocalError                         Traceback (most recent call last)

C:\Dokumente und Einstellungen\MECL User 1\<ipython console> in <module>()

C:\Dokumente und Einstellungen\MECL User 1\<ipython console> in foo()

UnboundLocalError: local variable 'x' referenced before assignment
Mit einer geposteten Fehlermeldung wäre das natürlich einfacher gewesen ;-)

@OP: Welche Bücher denn? Man ahnt da ja was :twisted:
mr.mc.mauser
User
Beiträge: 25
Registriert: Sonntag 4. September 2005, 01:18

@Hyperion du fragst welche Bücher:

Das Python Praxisbuch von Farid Hajji
Python Openbook von Gallileo Press
diese Beiden habe ich gelesen

dann habe ich noch das Python Ge-Packt von Michael Weigend
und Python kurz und Gut von O'reilly
und Natürlich das Wkibook Python unter Linux
diese Bücher nehme ich mehr oder weniger zum Nachschlagen

bestellt habe ich mir noch das Rapid GUI Programming with Python and QT von Mark Summerfield.

Jetzt habe ich mal im Praxisbuch nachgelesen was ich wollte (Seite 232), mir hatte eigentlich nur das Stichwort gefehlt.

Und ich habe definitiv die sache mit dem Global gemeint !
denn diese Variable brauche ich nicht nur in dieser Klasse sondern in meinem gesamten Programm immer und immer wieder
das war auch der Grund warum ganz oben X gesetzt wurde !!

Gruß
mc.mauser
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

mr.mc.mauser hat geschrieben:Und ich habe definitiv die sache mit dem Global gemeint !
denn diese Variable brauche ich nicht nur in dieser Klasse sondern in meinem gesamten Programm immer und immer wieder
das war auch der Grund warum ganz oben X gesetzt wurde !!
Mag sein, dass du das gemeint hast, allerdings solltest du dir vor Augen halten, dass globale Variablen zu aendern eine sehr grosse Fehlerquelle ist, die man vermeiden sollte.
lunar

@mr.mc.mauser: Das fällt dann genau unter den erwähnten Punkt "mangelnde Qualität". Wenn Du globale Attribute benötigst, ist beim Entwurf etwas schief gegangen.

Globale Attribute führen zu hoher Koppelung einzelner Teile der Anwendung, die in der Folge nicht mehr isoliert betrachtet werden können. Sie sind folglich nur in geringem Maße wiederverwendbar, zudem sehr schlecht wartbar, weil Änderungen Auswirkungen auf völlig unzusammenhängende Programmteile haben können, und schlecht testbar, weil jede einzelne Komponenten dann nicht nur einen internen Zustand hat, sondern auch von einem globalen Zustand abhängt.

Es hat schon seine Gründe, warum ich Dir sage, dass Du global nicht nutzen solltest.
Antworten