Übergabe von Listen bei objektorientierter Programmierung

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
TuXX
User
Beiträge: 24
Registriert: Sonntag 25. Juni 2017, 17:52

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!
Sirius3
User
Beiträge: 18274
Registriert: Sonntag 21. Oktober 2012, 17:20

Zeig Beispielcode.
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

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.
Benutzeravatar
__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
TuXX
User
Beiträge: 24
Registriert: Sonntag 25. Juni 2017, 17:52

Hier ein Beispiel:

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()

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!
Benutzeravatar
__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:

Code: Alles auswählen

In [321]: from pathlib import Path                                              

In [322]: Path.home()                                                           
Out[322]: PosixPath('/home/bj')
Zwischenstand:

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
Antworten