Hallo Forum,
Ich bin Anfänger im Bereich objektorientierter Programmierung. Nun bin ich auf das Problem gestossen, dass die in einer Funktion (def) erstellte Liste in einer anderen Funktion (def) nicht sichtbar ist. Ich habe Liste als globale Variable definiert (global List), aber das hatte auch keinen Einfluss. Wie kann ich Listen, Variablen etc. zwischen Funktionen übergeben bzw. für andere Funktionen verfügbar machen.
Danke für eure Hilfe!
Übergabe von Listen bei objektorientierter Programmierung
Bitte den relevanten Code zeigen.
Allgemein gilt
- globale Variablen sind ein Fehler, weil sie zu unübersichtlichen Programmzuständen führen.
- Werte werden an Funktion als Argumente übergeben, und verlassen sie als Rückgabewerte.
- in OOP können Werte in Form von Zustand des Objekts angelegt und benutzt werden.
Allgemein gilt
- globale Variablen sind ein Fehler, weil sie zu unübersichtlichen Programmzuständen führen.
- Werte werden an Funktion als Argumente übergeben, und verlassen sie als Rückgabewerte.
- in OOP können Werte in Form von Zustand des Objekts angelegt und benutzt werden.
- __blackjack__
- User
- Beiträge: 14054
- Registriert: Samstag 2. Juni 2018, 10:21
- Wohnort: 127.0.0.1
- Kontaktdaten:
Anmerkung bezüglich des Betreffs: Das lokale Namen aus einer Funktion nicht in anderen Funktionen sichtbar sind, hat nichts mit objektorientierter Programmierung (OOP) zu tun. Und auch das man keine globalen Variablen verwendet und Funktionen über Argumente und Rückgabewerte mit der ”Aussenwelt” kommunizieren sollten, damit es nicht unübersichtlich und fehleranfällig wird, hat auch nichts mit OOP zu tun. Das gilt bei OOP dann einfach genau so weiter für Methoden.
Code: Alles auswählen
#!/usr/bin/env python3
def create_some_values():
numbers = [42, 23, 4711]
return numbers
def do_something(values):
for value in values:
print("*", value)
def main():
magical_numbers = create_some_values()
do_something(magical_numbers)
if __name__ == "__main__":
main()
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
Hier ein Beispiel:
Der Plan ist mit "öffnen" die zu öffnende Datei festzulegen und im Minimalbeispiel den Pfad der Datei nach dem Druck von "Starten" auszugeben.
Mit dem vorliegenden Code gibt es zwei Schwierigkeiten:
* Der Pfad kann nicht übergeben werden.
* Der "Open file" Dialog wird beim drücken des "Starten"-Knopfes noch einmal ausgeführt.
Im Voraus vielen Dank für eure Hilfe!
Code: Alles auswählen
import tkinter as tk
from tkinter import ttk
from tkinter import filedialog
from tkinter import *
def openbutton():
tf = filedialog.askopenfilename(initialdir="C:/Users/Name", title="Open file",
filetypes=(("xlsx files", "*.xlsx"),))
return tf
def startbutton():
# Inhalt der Variable tf ausgeben
# Statt der Ausgabe des Pfades wird noch einmal der "Open file" Dialog geäffnet
print(openbutton())
# Benutzeroberfläche
root = tk.Tk()
root.title("Test")
root.geometry("600x500")
ButtonStart = tk.Button(root, text='Öffnen', command=openbutton)
ButtonEnde = tk.Button (root, text = 'Starten', command=startbutton)
ButtonStart.grid(row=0, column=2, padx=15, pady=15)
ButtonEnde.grid(row=1, column=2, padx=15, pady=15)
root.mainloop()
Mit dem vorliegenden Code gibt es zwei Schwierigkeiten:
* Der Pfad kann nicht übergeben werden.
* Der "Open file" Dialog wird beim drücken des "Starten"-Knopfes noch einmal ausgeführt.
Im Voraus vielen Dank für eure Hilfe!
- __blackjack__
- User
- Beiträge: 14054
- Registriert: Samstag 2. Juni 2018, 10:21
- Wohnort: 127.0.0.1
- Kontaktdaten:
@TuXX: Das geht nicht wirklich vernünftig mit Funktionen. Jede nicht-triviale GUI braucht objektorientierte Programmierung, also mindestens eine Klasse.
`ttk` wird importiert aber nicht verwendet. Sternchen-Importe sind Böse™. Da holt man sich gerade bei `tkinter` fast 200 Namen ins Modul von denen nur ein kleiner Bruchteil verwendet wird. Auch Namen die gar nicht in `tkinter` definiert werden, sondern ihrerseits von woanders importiert werden. Das macht Programme unnötig unübersichtlicher und fehleranfälliger und es besteht die Gefahr von Namenskollisionen. Du hast doch `tkinter` auch bereits als `tk` importiert und sprichst Objekte daraus über diesen Namen an.
Auf Modulebene sollte nur Code stehen der Konstanten, Funktionen, und Klassen definiert. Das Hauptprogramm steht üblicherweise in einer Funktion die `main()` heisst.
Die Fenstergrösse gibt man nicht vor wenn die automatisch vom Inhalt bestimmt wird.
Namen werden in Python klein_mit_unterstrichen geschrieben. Ausnahmen sind Konstanten (KOMPLETT_GROSS) und Klassen (PascalCase). Die Unterstriche kommen (ausser bei Klassen) zwischen die Worte.
Funktions- und Methodennamen beschreiben üblicherweise die Tätigkeit die diese Funktion oder Methode durchführt. `openbutton()` oder `startbutton()` wären tatsächlich auch Tätigkeiten, aber die beiden Funktionen öffnen ja keine Buttons.
Ausserdem sollte man auf die Reihenfolge der Worte achten (wenn man nicht Yoda ist). Das ist kein Knopfstart oder Knopfennde, sondern ein Startknopf und ein Endknopf. Wobei es sehr schräg ist einen Button `end_button` zu nennen und den mit "Starten" zu beschriften. WTF‽
Es gibt nur diese zwei Knöpfe in der GUI, die werden im Grid aber in die dritte Spalte gesetzt‽
Falls `initialdir` immer das Heimatverzeichnis des Benutzers sein soll, das kann man dynamisch ermitteln, und das sogar plattformunabhängig. Da muss man keine Windowspfade hart in den Quelltext schreiben:
Zwischenstand:
`ttk` wird importiert aber nicht verwendet. Sternchen-Importe sind Böse™. Da holt man sich gerade bei `tkinter` fast 200 Namen ins Modul von denen nur ein kleiner Bruchteil verwendet wird. Auch Namen die gar nicht in `tkinter` definiert werden, sondern ihrerseits von woanders importiert werden. Das macht Programme unnötig unübersichtlicher und fehleranfälliger und es besteht die Gefahr von Namenskollisionen. Du hast doch `tkinter` auch bereits als `tk` importiert und sprichst Objekte daraus über diesen Namen an.
Auf Modulebene sollte nur Code stehen der Konstanten, Funktionen, und Klassen definiert. Das Hauptprogramm steht üblicherweise in einer Funktion die `main()` heisst.
Die Fenstergrösse gibt man nicht vor wenn die automatisch vom Inhalt bestimmt wird.
Namen werden in Python klein_mit_unterstrichen geschrieben. Ausnahmen sind Konstanten (KOMPLETT_GROSS) und Klassen (PascalCase). Die Unterstriche kommen (ausser bei Klassen) zwischen die Worte.
Funktions- und Methodennamen beschreiben üblicherweise die Tätigkeit die diese Funktion oder Methode durchführt. `openbutton()` oder `startbutton()` wären tatsächlich auch Tätigkeiten, aber die beiden Funktionen öffnen ja keine Buttons.
Ausserdem sollte man auf die Reihenfolge der Worte achten (wenn man nicht Yoda ist). Das ist kein Knopfstart oder Knopfennde, sondern ein Startknopf und ein Endknopf. Wobei es sehr schräg ist einen Button `end_button` zu nennen und den mit "Starten" zu beschriften. WTF‽
Es gibt nur diese zwei Knöpfe in der GUI, die werden im Grid aber in die dritte Spalte gesetzt‽
Falls `initialdir` immer das Heimatverzeichnis des Benutzers sein soll, das kann man dynamisch ermitteln, und das sogar plattformunabhängig. Da muss man keine Windowspfade hart in den Quelltext schreiben:
Code: Alles auswählen
In [321]: from pathlib import Path
In [322]: Path.home()
Out[322]: PosixPath('/home/bj')
Code: Alles auswählen
#!/usr/bin/env python3
import tkinter as tk
from pathlib import Path
from tkinter.filedialog import askopenfilename
class MainWindow(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
self.title("Test")
self.file_path = None
tk.Button(self, text="Öffnen", command=self.select_file_path).grid(
row=0, column=0, padx=15, pady=15
)
tk.Button(self, text="Starten", command=self.start_whatever).grid(
row=1, column=0, padx=15, pady=15
)
def select_file_path(self):
filename = askopenfilename(
initialdir=Path.home(),
title="Open file",
filetypes=(("xlsx files", "*.xlsx"),),
)
if filename:
self.file_path = Path(filename)
def start_whatever(self):
print(
self.file_path
if self.file_path
else "Es wurde noch kein Pfad ausgewählt!"
)
def main():
MainWindow().mainloop()
if __name__ == "__main__":
main()
“Vir, intelligence has nothing to do with politics!” — Londo Mollari