Seite 1 von 1
Array speichern nach mehrfachen Funktionsaufruf
Verfasst: Dienstag 16. Juni 2015, 09:19
von felopy
Hallo,
habe ein kleines Anfängerproblem. Ich will mit askopenfilename einen String in ein Array bzw. Liste speichern, dies aber mehrfach ausführen.
Allerdings resetet es jedesmal mein Array, wenn ich die Funktion wieder aufrufe.
Kann mir da mal bitte jemand helfen?
Code: Alles auswählen
def array(self, liste):
daten_in = []
daten_in.append(liste)
#print(structs_in)
def einlesen(self):
eingabe = askopenfilename()
self.array(eingabe)
MfG
Felopy
Re: Array speichern nach mehrfachen Funktionsaufruf
Verfasst: Dienstag 16. Juni 2015, 09:24
von Sirius3
@felopy: was soll den die Funktion array machen? Bisher tut sie gar nichts, außer eine lokale Variable zu erzeugen und wieder zu verwerfen.
Re: Array speichern nach mehrfachen Funktionsaufruf
Verfasst: Dienstag 16. Juni 2015, 10:11
von felopy
sie soll nur das Array füllen und eben nicht jedesmal verwerfen.
Den Inhalt des Arrays will ich dann an andere Stelle nutzen.
Bsp.:
ich drück 3mal einen Button und jedesmal wähle ich eine andere Datei aus.
Ich hätte dann gerne ein Array mit den 3 ausgewählten Dateinamen
Re: Array speichern nach mehrfachen Funktionsaufruf
Verfasst: Dienstag 16. Juni 2015, 10:28
von Sirius3
@felopy: den Ausschnitt aus Deinem Programm, den Du gepostet hast, macht so überhaupt keinen Sinn. Wenn Du eine Liste mit "[]" erzeugst und dann ein Element anhängst, dann ist in dieser Liste ein Element, was aber wie gesagt egal ist, weil die Liste sofort wieder verworfen wird. Zeig ein lauffähiges Programm, das Dein Problem illustriert, beschreibe Dein erwartetes Verhalten und das tatsächliche Verhalten des Programms.
Re: Array speichern nach mehrfachen Funktionsaufruf
Verfasst: Dienstag 16. Juni 2015, 10:51
von felopy
wie kann ich denn verhindern, dass die Liste verworfen wird?
Re: Array speichern nach mehrfachen Funktionsaufruf
Verfasst: Dienstag 16. Juni 2015, 10:52
von Hyperion
@felopy: Dann musst Du Dir das Listenobjekt irgend wo *merken*! Konkreter kann man das ohne mehr Infos zum Kontext nicht beantworten...
Re: Array speichern nach mehrfachen Funktionsaufruf
Verfasst: Dienstag 16. Juni 2015, 12:02
von snafu
felopy hat geschrieben:Bsp.:
ich drück 3mal einen Button und jedesmal wähle ich eine andere Datei aus.
Ich hätte dann gerne ein Array mit den 3 ausgewählten Dateinamen
Dazu lautet der Pseudocode dann normalerweise:
Code: Alles auswählen
dateinamen = []
while not eingabe_abgeschlossen:
dateinamen.append(erfrage_dateiname())
verarbeite(dateinamen)
Was ich damit sagen will: Funktionen fummeln nicht an halb-fertigen Listen herum, sondern Listen werden entweder in einer Schleife nach und nach mit Funktionsrückgaben befüllt (wie im gezeigten Pseudocode) oder die Funktionen kümmern sich um die Erzeugung einer vollständigen Liste und geben diese vollständige Liste als Rückgabewert aus (entspräche Zeile 1-3 bei mir + `return` anstatt `verarbeite` in Zeile 4).
Du solltest deinen Code also so umbauen, dass er diesen Anforderungen entspricht. Und im Falle einer Schleife muss es dann eben eine definierte Abbruchbedingung geben, d.h. der Punkt, an dem die Liste nicht weiter befüllt wird, sollte feststehen (etwa: solange der Anwender nicht "Fertig" geklickt hat, werden weitere Eingaben erfragt).
Re: Array speichern nach mehrfachen Funktionsaufruf
Verfasst: Mittwoch 17. Juni 2015, 08:21
von felopy
soweit verstehe ich das, allerdings ist das mit der Abbruchbedingung verwirrend.. ich habe ja keine abfrage per "input("nochmal?")" sondern mache das über eine Button in einer GUI.
hier nochmal Beispielhaft was ich möchte:
Code: Alles auswählen
# -*- coding: utf-8 -*-
import tkinter
from tkinter.filedialog import askopenfilename
class MyApp(tkinter.Frame):
def __init__(self, master=None):
tkinter.Frame.__init__(self, master)
self.grid()
self.createWidgets()
def createWidgets(self):
self.button = tkinter.Button(root)
self.button["text"] = "Array Inhalt w�hlen"
self.button["command"] = self.arrayerstellen
self.button.grid(row=0,column=1)
def arrayerstellen(self):
global mein_array
mein_array = []
mein_array.append(askopenfilename())
def arraynutzen(self):
i = 0
while i < (len(mein_array)-1):
i=i+1
print(mein_array[i])
root = tkinter.Tk()
root.title("wasauchimmer")
app = MyApp(root)
app.mainloop()
Bei jedem Button-Klick erstelle ich das array neu, sodass immer nur ein Wert darin ist.. ich möchte aber, dass dieser reset nicht passiert und jeder Button-Klick das array um einen weitern Wert erweitert. Leider keine Ahnung wie ich das anstelle..
Re: Array speichern nach mehrfachen Funktionsaufruf
Verfasst: Mittwoch 17. Juni 2015, 08:32
von Sirius3
@felopy: das "Programm" das Du da gepostet hast ist immer noch nicht lauffähig. Wie soll man da mit einer Antwort ansetzen können, ohne raten zu müssen, was Du wahrscheinlich sonst noch so machst? "self" ist nicht definiert, ein Einrückungen sind kaputt, usw.
Du nutzt ja scheinbar eine Klasse, also ist die Klasse auch der richtige Ort um Dir Deine Liste "mein_array" zu merken.
Re: Array speichern nach mehrfachen Funktionsaufruf
Verfasst: Mittwoch 17. Juni 2015, 08:44
von felopy
habs editiert
Re: Array speichern nach mehrfachen Funktionsaufruf
Verfasst: Mittwoch 17. Juni 2015, 13:36
von BlackJack
@felopy: Ich denke Du solltest erst einmal Python lernen, also die Grundlagen, und dann ein bisschen in objektorientierter Programmierung (OOP) Fuss fassen, bevor Du eine GUI programmierst. Das Programm ist auf mehreren Ebenen sehr komisch. Bon den Grundlagen her: die ``while``-Schleife in `arraynutzen()` was so niemand in ernsthaft in Python ausdrücken würde. OOP: Eine ”Klasse” die ausser der unnötigerweise ausgelagerten Methode zum erzeugen von Widgets keine *echten* Methoden besitzt. ``global`` was in einer Klasse so überhaupt gar nichts zu suchen hat weil Klassen ja gerade dazu benutzt werden um so etwas zu vermeiden. Ein Wert der in einer Funktion/Methode einfach so aus dem Modul benutzt wird statt als Argument übergeben zu werden (`root`) und der damit die `MyApp`-Klasse noch ein Stück sinnloser macht weil in dem `Frame` den die Klasse beschreibt niemals irgend etwas angezeigt wird.
Und auch bei der GUI-Programmierung ist einiges im Argen. Widgets layouten sich nicht selbst. Kein Widget aus der Standardbibliothek macht das. Damit nimmt man dem Aufrufer der Klasse Entscheidungsspielräume wo und wie das Widget letztendlich dargestellt werden soll. Die Schaltfläche wird unnötig ”gesprächig” erstellt — man könnte Text und Rückruffunktion auch direkt beim Erstellen des Objekts angeben — und das Exemplar wird unnötigerweise an das `MyApp`-Exemplar gebunden.
Mal davon abgesehen das Array der falsche Begriff ist, sollten Grunddatentypen in der Regel nicht in Namen auftauchen, denn wenn man den Typ mal ändert hat man entweder falsche, irreführende Namen im Programm oder muss den Namen überall anpassen. Auch ist `arrayerstellen()` zwar genau das was die Funktion macht (also eigentlich ja eine Liste und kein Array) aber genau das willst Du ja eigentlich gar nicht. Wenn jemand auf die Schaltfläche drückt soll ja keine neue Liste erstellt werden, sondern offenbar möchtest Du das an eine vorhandene, anfangs leere Liste, ein neues Element angehängt wird.
Re: Array speichern nach mehrfachen Funktionsaufruf
Verfasst: Mittwoch 17. Juni 2015, 15:22
von bwbg
BlackJack kam mir zuvor. Nichts desto trotz möchte ich meinen Senf auch abgeben (auch wenn dieser so ziemlich dem von BlackJack entspricht):
Code: Alles auswählen
# -*- coding: utf-8 -*-
## Die Angabe DIESER Kodierung ist nicht notwendig. Python3 verwendet UTF-8 als
## Standardeinstellung. Allerdings sollte man sichergehen, dass die Datei auch
## UTF-8 kodiert ist.
## Die erste Zeile sollte das sogenannte Shebang sein. Dieses wird unter Windows
## normalerweise ignoriert, unixoide Systeme wählen den Interpreter jedoch
## danach aus.
import tkinter
from tkinter.filedialog import askopenfilename
## Per Konvention wird mit 4 Leerzeichen eingerückt.
class MyApp(tkinter.Frame):
def __init__(self, master=None):
tkinter.Frame.__init__(self, master)
## Es gibt die super()-Funktion zum Initialiserungsaufruf der Eltern-
## klasse
self.grid()
## Ein Widget (hier Frame) sollte sich nicht selbst layouten. Dies
## sollte immer das übergeordnete Widget übernehmen.
self.createWidgets()
## Die Aufteilung ist in diesem Minimalbeispiel nicht notwendig kann
## aber in komplexeren Widgets durchaus sinnvoll sein.
def createWidgets(self): ## s. o.
## Per Konvention sollten Funktions- und Methodennamen
## lower_case_with_underscores formatiert werden.
self.button = tkinter.Button(root)
## Es ist nicht nötig, den erzeugten Button an das Widget-Objekt zu
## binden. Das dem Button übergeordnete Widget "kennt" seine Kinder.
self.button["text"] = "Array Inhalt w�hlen"
self.button["command"] = self.arrayerstellen
## Die beiden Zeilen kannst Du in das Erzeugen des Buttons integrieren.
self.button.grid(row=0,column=1)
## Parameter sollten durch Komma+Leerzeichen getrennt werden.
def arrayerstellen(self):
## Die Funktion tut genau das, was ihr Name suggeriert. Es ist nur nicht
## das, was du willst, dass sie tut. Auch hier sollte der Name nach
## Konvention mit einem underscore versehen werden.
global mein_array
## Vergiss, dass es "global" überhaupt gibt. Vergiss es. Nicht da. Nein.
mein_array = []
mein_array.append(askopenfilename())
## Du erzeugst eine leere Liste (ein array ist im Python-Kontext etwas
## anderes), hängst eine Pfad an und verwirfst diese. Darüber hinaus
## ist ``mein_array`` absolut nichts sagend. Interessant ist zu wissen
## WAS man hinter dem Namen erwarten kann: Dateinamen.
def arraynutzen(self):
## Namenskonvention
i = 0
while i < (len(mein_array)-1):
i=i+1
print(mein_array[i])
## Ein klassisches Anti-Pattern. Wenn Du die Elemente einer Liste nutzen
## möchtest, dann verwende die for-Schleife.
root = tkinter.Tk()
root.title("wasauchimmer")
app = MyApp(root)
app.mainloop()
## Code auf Modulebene solltest Du immer vermeiden. Verwende statt dessen das
## s. g. Main-Idiom.
Auf die Gefahr hin, Deinen Lernerfolg zu mindern, ein Umsetzungsvorschlag, um Dich in die richtige Richtung zu schubsen:
Code: Alles auswählen
#!/usr/bin/env python3
import tkinter as tk
from tkinter.filedialog import askopenfilename
class MyFrame(tk.Frame):
def __init__(self, parent):
super().__init__(parent)
self.filenames = []
# In dieser Liste (welche an das Widget gebunden wird) werden die
# Dateinamen gespeichert.
tk.Button(self, text='Datei wählen', command=self.ask_filename).pack()
tk.Button(self, text='Verwenden', command=self.use_filenames).pack()
def ask_filename(self):
## Die Methode sollte besser 'add_filename' genannt werden, wie in
## einem Folgebetrag erwähnt wird.
self.filenames.append(askopenfilename())
def use_filenames(self):
for e in self.filenames:
print(e)
def main():
root = tk.Tk()
frame = MyFrame(root)
frame.pack()
root.mainloop()
if __name__ == '__main__':
main()
Re: Array speichern nach mehrfachen Funktionsaufruf
Verfasst: Mittwoch 17. Juni 2015, 15:29
von DasIch
Windows mag die Shebang ignorieren, Python unter Windows hat aber inzwischen einen Launcher der die nutzt um den richtigen Interpreter auszuwählen.
Re: Array speichern nach mehrfachen Funktionsaufruf
Verfasst: Mittwoch 17. Juni 2015, 16:09
von snafu
`ask_filename()` würde ich ja eher `add_filename()` nennen, weil da mehr als nur das Erfragen des Dateinamens geschieht. Das Erfragen per GUI ist lediglich der Weg, um an den benötigten Parameter zu kommen. Ziel der Methode ist das Hinzufügen, daher sollte sich dies entsprechend im Namen der Methode wiederfinden.
Re: Array speichern nach mehrfachen Funktionsaufruf
Verfasst: Mittwoch 17. Juni 2015, 16:51
von bwbg
DasIch hat geschrieben:Windows mag die Shebang ignorieren, Python unter Windows hat aber inzwischen einen Launcher der die nutzt um den richtigen Interpreter auszuwählen.
Das wusste ich noch nicht, danke für die Info.
snafu hat geschrieben:`ask_filename()` würde ich ja eher `add_filename()` nennen, weil da mehr als nur das Erfragen des Dateinamens geschieht. Das Erfragen per GUI ist lediglich der Weg, um an den benötigten Parameter zu kommen. Ziel der Methode ist das Hinzufügen, daher sollte sich dies entsprechend im Namen der Methode wiederfinden.
Recht hast du. Ich habe das in meinem Beitrag entsprechend kommentiert.
Re: Array speichern nach mehrfachen Funktionsaufruf
Verfasst: Freitag 19. Juni 2015, 08:45
von felopy
Danke bwbg,
das ich das array in der init Funktion erstellen muss war der Knackpunkt.
Funzt jetzt alles wie es soll

Re: Array speichern nach mehrfachen Funktionsaufruf
Verfasst: Freitag 19. Juni 2015, 09:44
von bwbg
Nun da Du das weißt, ist es an der Zeit, dass Du Dir Gedanken machst,
- warum das so ist und
- warum es nicht so funktioniert, wie Du es eingangs probiert hattest.