Einsteigerproblem: "globale" Variablen

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
mephisto-online
User
Beiträge: 167
Registriert: Sonntag 29. September 2013, 17:05

Hallo,

nach Durcharbeitung mehrerer Tutorials finde ich nicht so recht den Einstieg, nun etwas selber zu machen (Beispiele auszuprobieren und zu verstehen ist das Eine, selber machen das Andere... :? ).

Bei folgendem habe ich einfach keine Idee, warum es nicht geht:

Datei basicdataset.py:

Code: Alles auswählen

class DataSet(object):
    def __init__(self,
                 name1="leer",
                 name2="leer",
         self.__name1 = name1
         self.__name2 = name2
Datei main.py:

Code: Alles auswählen

import sys
from PyQt4 import QtGui
from mainwindow import Ui_MainWindow

import basicdataset

dataList = list()
dataSets = 0
actualMainSet = 0
actualRefSet = 0

class DataPy(QtGui.QMainWindow):


    def __init__(self):
        super(DataPy, self).__init__()
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)
        self.show()

    def closeEvent(self, event):

        reply = QtGui.QMessageBox.question(self, 'Hinweis',
                                           "Wirklich beenden ?", QtGui.QMessageBox.Yes |
                                                                 QtGui.QMessageBox.No, QtGui.QMessageBox.No)

        if reply == QtGui.QMessageBox.Yes:
            event.accept()
        else:
            event.ignore()

def newDataSet():
    dataList.append(basicdataset)
    dataSets += 1
        
def main():
    app = QtGui.QApplication(sys.argv)
    ex = DataPy()
    sys.exit(app.exec_())


if __name__ == '__main__':
    main()

In newDataSet() bekomme ich bei "dataSets += 1" ein "unresolved reference", bei "dataList.append(basicdataset)" nicht ! Warum ? Geht das nicht so mit "globalen" Variablen ? Oder habe ich was anderes Blödes gemacht ?
BlackJack

@mephisto-online: Bei ``dataSets += 1`` versuchst Du den *lokalen* Namen `dataSets` an den alten Wert der an diesen Namen gebunden ist plus 1 zu binden, nur das an den *lokalen* Namen vorher noch kein Wert gebunden wurde den man erhöhen könnte. Bei ``dataList.append(basicdataset)`` wird kein Name neu gebunden sondern ein vorhandenes Objekt, die Liste, verändert. Immer wenn der Compiler in einer Funktion eine Zuweisung an einen Namen sieht, dann ist das ein lokaler Name. Namen denen nichts zugewiesen wird, müssen „in der Umgebung” der Funktion existieren, spätestens wenn die Funktion ausgeführt wird. In diesem Fall ist „die Umgebung” das Modul.

Man kann dem Compiler mitteilen das Namen denen etwas zugewiesen wird innerhalb einer Funktion trotzdem nicht lokal sein sollen, aber das wäre die ”falsche” Lösung, denn auf Modulebene sollte es beide Werte eigentlich nicht geben, denn es sind ja beides offensichtlich keine Konstanten.

Konkrete Datentypen sollte man aus Namen heraus halten. Wenn man den tatsächlichen Typ einmal ändert, dann muss man überall den Namen anpassen, oder man hat einen Namen der nicht mehr zum Typ passt und damit den Leser, im Ernstfall also auch einen selbst, in die Irre führt. `dataSets` steht gar nicht für Datenmengen sondern die Anzahl der Datenmengen, also eher `datasets_count` oder `datasets_length`. Beim letzten Namen wird vielleicht deutlich warum man diese Variable überhaupt nicht braucht wenn sie einfach nur die Länge von `dataList` angeben soll, denn *die* kann man jederzeit mit `len()` abfragen.

Mein Gefühl sagt mir das Du `actual*` durch `current*` ersetzen möchtest. Und die beiden sehen mir weder von der Schreibweise des Namens noch von der vermuteten Semantik nach Namen aus die auf Modulebene existieren sollten.

Eigentlich solltest Du einen ganz anderen Fehler sehen, denn ``basicdataset.py`` wird so wie es dort steht vom Compiler nicht ohne Syntaxfehlermeldung übersetzt.

Bei den Attributen solltest Du aus den zwei führenden Unterstrichen jeweils einen machen. Das ist die in Python übliche Konvention um dem Leser mitzuteilen, dass ein Attribut nicht zur öffentlichen API gehört.

Im Hauptprogramm wird übrigens immer wieder das Modul-Objekt `basicdataset` an die Liste angehängt, was mir recht sinnfrei erscheint. Man würde dort wohl eher Exemplare von `basicdataset.DataSet` erstellen und in die Liste stecken.
Sirius3
User
Beiträge: 17738
Registriert: Sonntag 21. Oktober 2012, 17:20

@mephisto-online: Dein erster Fehler ist, daß Du globale Variablen verwenden willst. »dataSets« ist eine Variable, die unnötig ist. Willst Du wissen, wieviele Elemente »dataList« enthält, kannst Du das einfach über »len(dataList)« herausfinden. »dataList« hingegen wird ja in irgendeinem Kontext gebraucht, zum Beispiel im Daten zu speichern, die im Fenster »DataPy« dargestellt werden. Dann sollte »dataList« auch in Attribut von »DataPy« sein.
Die Funktion »newDataSet« macht auch seltsame Dinge. Willst Du tatsächlich das Modul »basicdataset« in die Liste einfügen? Du meintest wahrscheinlich »basicdataset.DataSet()«. Dann ist es aber unüblich ein Objekt zu einer Liste hinzuzufügen, ohne seine Init-Parameter setzten zu können. Das würde ja bedeuten, daß man nachträglich das Objekt nochmals ändern muß, die Liste also unfertige Objekte enthält. Eine andere Methode, die auf die Liste zugreift, könnte dadurch verwirrt werden.
Bei Deinem »DataSet«-Objekt sind die zweifachen Unterstriche mindestens einer zu viel. Wahrscheinlich sogar zwei, weil im Normalfall ein Data-Set Daten zur Verfügung stellt, seine Attribute damit öffentlich sind.
mephisto-online
User
Beiträge: 167
Registriert: Sonntag 29. September 2013, 17:05

Danke, danke ! Tut zwar weh :( , aber hilft bestimmt ! :D

Dann mal los, vielleicht von hinne nach vonne:
Sirius3 hat geschrieben:@mephisto-online: Dein erster Fehler ist, daß Du globale Variablen verwenden willst. »dataSets« ist eine Variable, die unnötig ist. Willst Du wissen, wieviele Elemente »dataList« enthält, kannst Du das einfach über »len(dataList)« herausfinden.
Stimmt, ist einfacher !
Sirius3 hat geschrieben: »dataList« hingegen wird ja in irgendeinem Kontext gebraucht, zum Beispiel im Daten zu speichern, die im Fenster »DataPy« dargestellt werden. Dann sollte »dataList« auch in Attribut von »DataPy« sein.
Das Hauptfenster soll die Benutzeroberflache sein, mit Buttons und der Datensatzliste, wo man dann jeweils einen Basis-Satz und einen Referenz-Satz auswählen kann und natürlich auch die Aktionen auslösen, die dann irgendwas mit denen machen. Die sollen dann aber jeweils separat in einem anderen Fenster/Widget erscheinen. Dafür möchte ich mehrere Module/Files machen (Calc, Graphics, File_IO, Db_IO). Ok, die Daten, BasisSet-Nr. und RefSet-Nr. kann ich natürlich dann parametrisch an andere Kontexte übergeben.
Sirius3 hat geschrieben: Die Funktion »newDataSet« macht auch seltsame Dinge. Willst Du tatsächlich das Modul »basicdataset« in die Liste einfügen?
Ja, das ist Quatsch so !
Sirius3 hat geschrieben: Du meintest wahrscheinlich »basicdataset.DataSet()«. Dann ist es aber unüblich ein Objekt zu einer Liste hinzuzufügen, ohne seine Init-Parameter setzten zu können. Das würde ja bedeuten, daß man nachträglich das Objekt nochmals ändern muß, die Liste also unfertige Objekte enthält. Eine andere Methode, die auf die Liste zugreift, könnte dadurch verwirrt werden.
Mein Plan war, der DataSet-Klasse noch eine Funktion (z.B. change_Data(...)) zu verpassen, in der ich die __init__-Methode mit Parametern aufrufen kann, um die Attribute zu ändern. Die Liste soll also tatsächlich modifizierbare Objekte haben.
Sirius3 hat geschrieben: Bei Deinem »DataSet«-Objekt sind die zweifachen Unterstriche mindestens einer zu viel. Wahrscheinlich sogar zwei, weil im Normalfall ein Data-Set Daten zur Verfügung stellt, seine Attribute damit öffentlich sind.
Ich hatte gelernt, dass die zwei Unterstriche Attribute privat machen. So hatte ich mir das ja auch vorgestellt. Änderungen halt dann mit der "change_data"-Funktion
BlackJack hat geschrieben:Bei ``dataSets += 1`` versuchst Du den *lokalen* Namen `dataSets` an den alten Wert der an diesen Namen gebunden ist plus 1 zu binden, nur das an den *lokalen* Namen vorher noch kein Wert gebunden wurde den man erhöhen könnte.
Genau das verstehe ich nicht. Mit dataSets=0 am Anfang wollte ich den Namen global erzeugen/binden und auf den wollte ich dann in newDataSet() zugreifen. Das ist eigentlich die wesenliche Frage, die ich jetzt hier hatte.
BlackJack hat geschrieben: Immer wenn der Compiler in einer Funktion eine Zuweisung an einen Namen sieht, dann ist das ein lokaler Name. Namen denen nichts zugewiesen wird, müssen „in der Umgebung” der Funktion existieren, spätestens wenn die Funktion ausgeführt wird. In diesem Fall ist „die Umgebung” das Modul.
Den Namen gibt es doch global mit dem Wert 0, Wie kann man denn lokal auf eine existierende globale Variabe zugreifen ? Globale Variabe lokal erzeugen geht mit global blabla, das weiss ich. Aber dataSets gibt es ja schon global.
BlackJack hat geschrieben: *die* kann man jederzeit mit `len()` abfragen.
Ja, *die* braucht man nicht.
BlackJack hat geschrieben: Mein Gefühl sagt mir das Du `actual*` durch `current*` ersetzen möchtest. Und die beiden sehen mir weder von der Schreibweise des Namens noch von der vermuteten Semantik nach Namen aus die auf Modulebene existieren sollten.
Da weiss ich jetzt nicht, was Du meinst
BlackJack hat geschrieben: Eigentlich solltest Du einen ganz anderen Fehler sehen, denn ``basicdataset.py`` wird so wie es dort steht vom Compiler nicht ohne Syntaxfehlermeldung übersetzt.
PyCharm meckert nicht und das Programm läuft bis hier auch.
BlackJack hat geschrieben: Bei den Attributen solltest Du aus den zwei führenden Unterstrichen jeweils einen machen. Das ist die in Python übliche Konvention um dem Leser mitzuteilen, dass ein Attribut nicht zur öffentlichen API gehört.
Ich hatte es jetzt halt so gelernt, dass man mir den zwei Unterstrichen private Attribute definiert.

Grüße
mephisto
Sirius3
User
Beiträge: 17738
Registriert: Sonntag 21. Oktober 2012, 17:20

@mephisto: lokal definierte Variablen haben immer Vorrang vor globalen, und »dataSets« wird nunmal auch lokal definiert. Um es noch mal zu betonen: auf Modulebene solltest Du nur Konstanten (also Objekte, die sich nicht verändern, also auch keine veränderbaren Listen), Klassen und Funktionen definieren.
BlackJack

@mephisto-online: Die `__init__()`-Methode nachträglich noch mal aufrufen ist keine gute Idee. Das ist ungewöhnlich und damit rechnet deshalb niemand.

Vergiss das „zwei Unterstriche == privat” am besten wieder. Das machen Leute die irgendwie zwanghaft so etwas wie ``public``, ``protected``, und ``private`` aus anderen Programmiersprachen auf Python abbilden wollen und mental nicht damit klar kommen dass es so etwas nicht in jeder Programmiersprache geben muss. :-) Kapselung und Zugriffschutz sind nicht synonym.

„Actual” heisst nicht „aktuell” sondern „eigentlich”, „tatsächlich”, „wirklich”. Und Konstanten auf Modulebene schreibt man konventionell KOMPLETT_IN_GROSSBUCHSTABEN. Wenn es denn Konstanten wären, was sie ja nicht sind.

Wenn Python das Modul kompilieren kann, dann hast Du hier nicht den tatsächlichen (wir erinnern uns: „actual” :-)) Inhalt der Date gezeigt, denn Zeile 4 sollte nicht mit einem Komma sondern einer schliessenden Klammer enden.

Code: Alles auswählen

In [18]: %cpaste
Pasting code; enter '--' alone on the line to stop or use Ctrl-D.
:class DataSet(object):
:    def __init__(self,
:                 name1="leer",
:                 name2="leer",
:         self.__name1 = name1
:         self.__name2 = name2
:--
  File "<ipython-input-18-344c9d6e753b>", line 5
    self.__name1 = name1
        ^
SyntaxError: invalid syntax
mephisto-online
User
Beiträge: 167
Registriert: Sonntag 29. September 2013, 17:05

Hallo,

@Sirius3
Sirius3 hat geschrieben:lokal definierte Variablen haben immer Vorrang vor globalen, und »dataSets« wird nunmal auch lokal definiert.
Ok, ist bislang in den Tuts nicht rübergekommen. Danke ! Wichtige Info !
Sirius3 hat geschrieben:Um es noch mal zu betonen: auf Modulebene solltest Du nur Konstanten (also Objekte, die sich nicht verändern, also auch keine veränderbaren Listen), Klassen und Funktionen definieren.
Lokal kann man also wohl darauf zugreifen, aber nicht verändern. "lokale Variable = globale Konstante" wäre also ok. Verstehe. :|

@BlackJack
Die __init__(...) sowohl zum initialisieren, als auch dann mit einer Klassen-Funktion auch zum Ändern zu benutzen ist nicht meine Idee, ist mir glaube ich sogar hier vorgeschlagen worden, damit man, wenn man, wie bei mir, etwa 14 attribute hat, das alles nicht zwei mal schreiben muss.
BlackJack hat geschrieben: Vergiss das „zwei Unterstriche == privat” am besten wieder. Das machen Leute die irgendwie zwanghaft so etwas wie ``public``, ``protected``, und ``private`` aus anderen Programmiersprachen auf Python abbilden wollen und mental nicht damit klar kommen dass es so etwas nicht in jeder Programmiersprache geben muss. :-) Kapselung und Zugriffschutz sind nicht synonym.
Ist richtig, kommt von meiner schlechten Vergangenheit mit Java & Co. ! Kann ich mir also getrost wieder abgewöhnen. Ok ! :D

Mein Spruch zu meiner Frau war immer, wenn ich mich mal wieder über Java aufgeregt hatte: "In Java macht man sich echt dauernd die Hose mit der Kneifzange zu". :wink:
BlackJack hat geschrieben: KOMPLETT_IN_GROSSBUCHSTABEN
Nach solchen Konventionen hatte ich mal näher gesucht und da schreiben die einen so und die anderen so. Ein richtiger Standard kommt da nicht rüber. Der Lehrstoff im Internet ist da mitunter echt Müll. Gut, dass es Euch hier gibt ! :P

Weil meine Attributliste so lang ist, habe ich lange gesucht, wie man die Liste in einer neuen Zeile fortsetzen kann. Dabei hatte ich zwei Lösungen gefunden: entweder die Attribut-Zeile mit '\' zu unterbrechen (aber wie dann in der nächsten Zeile weiter, wurde nicht gesagt. Bei Python aber extrem wichtig...), oder die Attribute unter dem ersten "Parameter" "self" anzuordnen, damit der Interpreter es akzeptiert.

So war es gemeint (halt nur mit 2 Attributen):

Code: Alles auswählen

    
def __init__(self, name1="leer", name2="leer"):
    self.__name1 = name1
    self.__name2 = name2


Grüße
mephisto
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

mephisto-online hat geschrieben:
Sirius3 hat geschrieben:Um es noch mal zu betonen: auf Modulebene solltest Du nur Konstanten (also Objekte, die sich nicht verändern, also auch keine veränderbaren Listen), Klassen und Funktionen definieren.
Lokal kann man also wohl darauf zugreifen, aber nicht verändern. "lokale Variable = globale Konstante" wäre also ok. Verstehe. :|
Nein, das bedeutet nicht mehr als das, was Sirius gesagt hat: auf modulebene schreibst du nur Konstanten, Definitionen von Klassen und Funktionen und ggf. Import-Anweisungen. Mehr soll da nicht stehen. Alles was veränderbar ist, gehört dort nicht hin. Per Konvention, nicht irgendwie über einen magischen Mechanismus.

mephisto-online hat geschrieben:Die __init__(...) sowohl zum initialisieren, als auch dann mit einer Klassen-Funktion auch zum Ändern zu benutzen ist nicht meine Idee, ist mir glaube ich sogar hier vorgeschlagen worden, damit man, wenn man, wie bei mir, etwa 14 attribute hat, das alles nicht zwei mal schreiben muss.
Da hast du sicher etwas falsch verstanden, welcher Thread soll das denn sein?

mephisto-online hat geschrieben:
BlackJack hat geschrieben:Kapselung und Zugriffschutz sind nicht synonym.
Ist richtig, kommt von meiner schlechten Vergangenheit mit Java & Co. ! Kann ich mir also getrost wieder abgewöhnen. Ok ! :D
Das hat nichts mit schlechter Javavergangenheit zu tun, sondern mit der Sprache. In Java muss man so vorgehen, wenn man die Schnittstellen stabil halten will. In Python ist das nicht notwendig, da man dies auch im Nachhinein für Attribute einführen kann, ohne das es von außen bemerkt wird.
mephisto-online hat geschrieben:Nach solchen Konventionen hatte ich mal näher gesucht und da schreiben die einen so und die anderen so. Ein richtiger Standard kommt da nicht rüber. Der Lehrstoff im Internet ist da mitunter echt Müll. Gut, dass es Euch hier gibt ! :P
PEP 8 wurde dir sicher schon empfohlen ;-)
mephisto-online hat geschrieben:Weil meine Attributliste so lang ist, habe ich lange gesucht, wie man die Liste in einer neuen Zeile fortsetzen kann. Dabei hatte ich zwei Lösungen gefunden: entweder die Attribut-Zeile mit '\' zu unterbrechen (aber wie dann in der nächsten Zeile weiter, wurde nicht gesagt. Bei Python aber extrem wichtig...), oder die Attribute unter dem ersten "Parameter" "self" anzuordnen, damit der Interpreter es akzeptiert.
Das hat nichts damit zu tun, wo du die Parameter hinschreibst. Wenn du ein öffnende Klammer hast, egal of (, [ oder {, dann kannst du so viele neue Zeilen machen und beliebig einrücken wie du lustig bist. Die Zeile ist dann "logisch" noch nicht zu ende.
Das Leben ist wie ein Tennisball.
BlackJack

@mephisto-online: Wenn man 14 Attribute auf einen Schlag neu setzen will dann riecht das aber auch irgendwie nach Entwurfsfehler. Das würde ja den kompletten Inhalt austauschen und dann würde man eher ein neues Objekt mit dem neuen Inhalt erstellen.

Konstantennamen in Grossbuchstaben ist in einigen Programmiersprachen üblich. Da gibt es eigentlich in der Regel wenig bis gar keine Diskussionen drüber. Im Gegensatz zu `mixedCase` vs. `words_with_underlines`. Letzteres wird vom Style Guide for Python Code nahegelegt.

Solange noch geöffnete Klammern existieren zu denen noch nicht das schliessende Gegenstück vorkam, weiss der Compiler, dass die ”logische” Zeile noch nicht abgeschlossen sein kann, und dann braucht man kein ``\`` am Zeilenende. Ich persönlich würde die Folgezeilen nicht unter dem `self` ausrichten weil man dann den Methodennamen nicht mehr ändern kann ohne dass man bei einer veränderten Länge des Namens nicht auch alle am `self` ausgerichteten Folgezeilen ändern muss. Das macht zum einen Arbeit und lenkt in der Versionsverwaltung von der tatsächlich wichtigen Veränderung ab. Den Name von `__init__` wird man natürlich eher nicht ändern, aber dort eine andere Formatierung als bei anderen Methoden zu machen ist IMHO auch nicht wirklich sinnvoll.
mephisto-online
User
Beiträge: 167
Registriert: Sonntag 29. September 2013, 17:05

@EyDu
EyDu hat geschrieben:... auf modulebene schreibst du nur Konstanten, Definitionen von Klassen und Funktionen und ggf. Import-Anweisungen. Mehr soll da nicht stehen. Alles was veränderbar ist, gehört dort nicht hin. Per Konvention, nicht irgendwie über einen magischen Mechanismus.
Das bei Python keine "magischen" Mechanismen existieren, ist mir schon sonnenklar. Und auf Modulebene definierte Konstanten (Konstanten ! ja, habe ich tatsächlich kapiert !) kann man doch besimmt irgendwo benutzen, oder ? Vielleicht auch innerhalb einer Funktion ?
EyDu hat geschrieben: Da hast du sicher etwas falsch verstanden, welcher Thread soll das denn sein?
Dann habe ich das halt auch nur in meinem "magischen" Kontext.
EyDu hat geschrieben: Das hat nichts mit schlechter Javavergangenheit zu tun, sondern mit der Sprache.
Gut, dass Du das sagst. Muss ich wohl mal echt drüber nachdenken :oops:
EyDu hat geschrieben: In Java muss man so vorgehen, wenn man die Schnittstellen stabil halten will. In Python ist das nicht notwendig, da man dies auch im Nachhinein für Attribute einführen kann, ohne das es von außen bemerkt wird.
Ich wollte Java jetzt nicht schlecht machen. Eigentlich geht es mir hier jetzt auch eignetlich nicht um Java.
Aber irgendwelche Bemerkungen über andere Sprachen und was sie für MICH (nicht generell !) bedeuten, sollte ich hier doch lieber lassen. Irgend jemand fühlt sich wohl immer auf den Schlips getreten.
EyDu hat geschrieben: PEP 8 wurde dir sicher schon empfohlen ;-)
PyCharm testet vielleicht auf PEP8 ? Das tut wohl jede bessere Python-IDE.
EyDu hat geschrieben: Das hat nichts damit zu tun, wo du die Parameter hinschreibst. Wenn du ein öffnende Klammer hast, egal of (, [ oder {, dann kannst du so viele neue Zeilen machen und beliebig einrücken wie du lustig bist. Die Zeile ist dann "logisch" noch nicht zu ende.
Danke, das ist mal ne wirklich eindeutige Aussage ! Danke !

Tja, tut mir leid, bin in sowas ein "Erbsenzähler" und wenn ich es nicht irgendwo eineindeutig lese, dann schwimme ich im "Magischen" rum.

Sorry EyDu

@BlackJack
BlackJack hat geschrieben:Wenn man 14 Attribute auf einen Schlag neu setzen will dann riecht das aber auch irgendwie nach Entwurfsfehler. Das würde ja den kompletten Inhalt austauschen und dann würde man eher ein neues Objekt mit dem neuen Inhalt erstellen.
Nein, nicht alle auf einmal, nur das erste Mal. Danach möchte man vielleicht mal einzelne ändern, damit neu rechnen und mit den anderen in der Liste vergleichen. Ist ja jetzt auch hinfällig, weil ich an die Attribute ja auch einzeln dran komme, wenn ich sie nicht "private" mache.
BlackJack hat geschrieben: Konstantennamen in Grossbuchstaben ist in einigen Programmiersprachen üblich. Da gibt es eigentlich in der Regel wenig bis gar keine Diskussionen drüber. Im Gegensatz zu `mixedCase` vs. `words_with_underlines`. Letzteres wird vom Style Guide for Python Code nahegelegt.
Ja, das ist PEP8. Das ist ja letztendlich auch das, was ich gesucht hatte.
BlackJack hat geschrieben: ...Ich persönlich würde die Folgezeilen nicht unter dem `self` ausrichten weil man dann den Methodennamen nicht mehr ändern kann ohne dass man bei einer veränderten Länge des Namens nicht auch alle am `self` ausgerichteten Folgezeilen ändern muss.
Das nervt mich auch, einfach nur Einrücken geht dann ja auch.
BlackJack hat geschrieben: ...Den Name von `__init__` wird man natürlich eher nicht ändern...
Hier im Ruhrpott würde man sagen: Iss klar !

Um das Thema hier abzuschliessen, mein Resümee: Keine globale Variablen !

Danke zusammen !
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

mephisto-online hat geschrieben:Das bei Python keine "magischen" Mechanismen existieren, ist mir schon sonnenklar. Und auf Modulebene definierte Konstanten (Konstanten ! ja, habe ich tatsächlich kapiert !) kann man doch besimmt irgendwo benutzen, oder ? Vielleicht auch innerhalb einer Funktion ?
Ja, die kannst du wie jede andere Variable auch benutzen, du solltest sie lediglich nicht ändern:

Code: Alles auswählen

KONSTANTE = 42

def spam(x):
    print KONSTANTE*x
mephisto-online hat geschrieben:
EyDu hat geschrieben: In Java muss man so vorgehen, wenn man die Schnittstellen stabil halten will. In Python ist das nicht notwendig, da man dies auch im Nachhinein für Attribute einführen kann, ohne das es von außen bemerkt wird.
Ich wollte Java jetzt nicht schlecht machen. Eigentlich geht es mir hier jetzt auch eignetlich nicht um Java.
Aber irgendwelche Bemerkungen über andere Sprachen und was sie für MICH (nicht generell !) bedeuten, sollte ich hier doch lieber lassen. Irgend jemand fühlt sich wohl immer auf den Schlips getreten.
Nee, es geht hier nicht um Befindlichkeiten. Das ist ein rein technisches Thema. An einem Beispiel wird das vielleicht etwas deutlicher: wenn du in Java ein Attribut als public deklarierst, dann legst du damit auch die Schnittstelle der Klasse fest. Falls sich die Implementierung dahinter ändert, dann hast du unter Umständen ein kleines Problem. Daher sind Attribute dann in der Regel private und der Zugriff erfolgt über Methoden. Sonst müssten ggf. jede Menge Attributzugriffe in Methoden verändert werden.

In Python hingegen kannst du Attribute nachträglich verändern. Man kann weiter ganz normal über den .-Operator auf das Attribut zugreifen, im Hintergrund läuft dann aber eine beliebige Methode. Die kann dann als privat markierte Attribute zugreifen oder zusätzliche Berechnungen durchführen. Die Schnittstelle bleibt also gleich. Such einfach mal im Zusammenhang mit Python nach "property".
mephisto-online hat geschrieben:Nein, nicht alle auf einmal, nur das erste Mal. Danach möchte man vielleicht mal einzelne ändern, damit neu rechnen und mit den anderen in der Liste vergleichen. Ist ja jetzt auch hinfällig, weil ich an die Attribute ja auch einzeln dran komme, wenn ich sie nicht "private" mache.
Ich weiß nicht, ob es schon erwähnt wurde, aber mit zwei führende Unterstriche sind nicht nur nicht privat, du kannst noch immer auf sie zugreifen. "Name Mangling" ist hier das Stichwort:

Code: Alles auswählen

>>> class Spam(object):
...     def __init__(self, x):
...         self.__ham = x
... 
>>> s = Spam(42)
>>> print s._Spam__ham
42
mephisto-online hat geschrieben:Um das Thema hier abzuschliessen, mein Resümee: Keine globale Variablen !
Dass fasst es gut zusammen ;-)
Das Leben ist wie ein Tennisball.
Antworten