Klassen. Attribute, Methoden für eine tkinter GUI? Wozu?
@Alfons Mittelmeyer: da hilft auch keine Fettschrift. Das ist einfach nur Quatsch. Was sollen denn bitte Methoden simulieren? Klassen sind dazu da, um Methoden mit ihren Daten zu bündeln. Das steht in jedem Tutorial im ersten Abschnitt.
-
- User
- Beiträge: 1715
- Registriert: Freitag 31. Juli 2015, 13:34
Ist doch einfach, wenn ich schreibe:Sirius3 hat geschrieben:@Alfons Mittelmeyer: da hilft auch keine Fettschrift. Das ist einfach nur Quatsch. Was sollen denn bitte Methoden simulieren? Klassen sind dazu da, um Methoden mit ihren Daten zu bündeln. Das steht in jedem Tutorial im ersten Abschnitt.
Code: Alles auswählen
application.init(master)
Man kann das so schreiben, aber das hat genauso wenig Sinn, wie den ganzen anderen Quatsch, den Du hier schreibst und ihn als unumstößliche Wahrheit anpreist. Wenn Du keine Ahnung hast, kannst Du gerne Fragen, aber hör auf damit, Deine kruden Ansichten Anfängern als Lösungen unterzujubeln.
- noisefloor
- User
- Beiträge: 4158
- Registriert: Mittwoch 17. Oktober 2007, 21:40
- Wohnort: WW
- Kontaktdaten:
Hallo,
@Sirius3: ich glaube ja manchmal, dass Alfons in einem Paralleluniversum Python gelernt hat und das Python da halt nicht dem idomatischen Python entspricht, was wir so programmieren. Ich bin allerdings noch unschlüssig, um dieses Python diesseits oder jenseits meiner Toleranzschwelle liegt
Gruß, noisefloor
Go ist genau wie C eine kompilierende Sprache. Nur für den Fall, dass du ein anderes Go kennst als ich: ich meine das Go hier https://golang.org/Mit Go gibt es das oder so ähnlich eben auch als Interpreter.
Für tkinter GUI nach deiner Ansicht ja jedenfalls scheinbar nicht. Wie du weiter oben im Thread "eindrucksvoll" demonstriert hast.Ich schreib ja nicht, dass man sie nicht braucht. Da Frage war doch, wofür man sie braucht.
@Sirius3: ich glaube ja manchmal, dass Alfons in einem Paralleluniversum Python gelernt hat und das Python da halt nicht dem idomatischen Python entspricht, was wir so programmieren. Ich bin allerdings noch unschlüssig, um dieses Python diesseits oder jenseits meiner Toleranzschwelle liegt

Gruß, noisefloor
-
- User
- Beiträge: 1715
- Registriert: Freitag 31. Juli 2015, 13:34
Es macht total viel Sinn, statt viele Klassen in einem Script zu haben, etliche Module zu haben. Statt lang in einem großen Script zu suchen, erinnert man sich meist an den Dateinamen für die GUI Komponente. Und in dieser Datei ist man von vielem anderem Code der nicht dazugehört, nicht abgelenkt und kommt auch nicht auf die Idee irgendwelche Querverweise auf anderes zu implementieren.Sirius3 hat geschrieben:Man kann das so schreiben, aber das hat genauso wenig Sinn, wie den ganzen anderen Quatsch, den Du hier schreibst und ihn als unumstößliche Wahrheit anpreist. Wenn Du keine Ahnung hast, kannst Du gerne Fragen, aber hör auf damit, Deine kruden Ansichten Anfängern als Lösungen unterzujubeln.
Solche Module sind sehr übersichtlich. Ich habe einmal das Programm in Module aufgeteilt:
Code: Alles auswählen
# === GUI Applikation ====
application.py
- application_gui.py
- - lift_frame_gui.py
- - - remote_manager_gui.py
- - - page_one_gui.py
- - - page_two_gui.py
- main_menu_gui.py
- - manager_menu_gui.py
- - hilfe_menu_gui.py
# === Helper Modules =====
tk.py
eventbroker.py
Kommen wir zu den Helper Modulen. Wenn man so etwas hat wie tk.py braucht man nicht immer zwischen tkinter und Tkinter zu unterscheiden, auch läßt sich leicht DynTkInter einbinden.
Ein sehr einfaches Modul ist tk.py:
Code: Alles auswählen
try:
from tkinter import *
except ImportError:
from Tkinter import *
Code: Alles auswählen
class EventBroker():
def __init__(self):
self._dictionary_ = {}
def subscribe(self,message_id,callback):
self._dictionary_[message_id] = callback
def publish(self,message_id,*args,**kwargs):
self._dictionary_[message_id](*args,**kwargs)
eventbroker = EventBroker()
publish = eventbroker.publish
subscribe = eventbroker.subscribe
Da man darauf besteht, daß man zuerst sein Programm startet und dann erst die GUI nachlädt, hatt man dann ein Script File.
application.py
Code: Alles auswählen
import tk
import application_gui
def main():
root = tk.Tk()
application_gui.init(root)
# eigener Code
root.mainloop()
main()
Das ist dann die GUI.
application_gui.py
Code: Alles auswählen
import tk
import lift_frame_gui
import main_menu_gui
def init(self):
# GUI ==============================
lift_frame = tk.Frame(self,name='lift_frame')
main_menu = tk.Menu(self,name='main_menu')
self['menu'] = main_menu
lift_frame.pack(fill='both', expand=1)
lift_frame_gui.init(lift_frame)
main_menu_gui.init(main_menu)
# END GUI ===========================
Das dürfe bei diesem lift_frame aber anders werden.
lift_frame_gui.py
Code: Alles auswählen
import tk
import remote_manager_gui
import page_one_gui
import page_two_gui
from eventbroker import subscribe,publish
def init(self):
# GUI ==============================
self.rowconfigure(0,weight=1)
self.columnconfigure(0,weight=1)
remote_manager = tk.Frame(self,name='remote_manager')
page_one = tk.Frame(self,name='page_one')
page_two = tk.Frame(self,name='page_two')
remote_manager.grid(row=0,sticky = 'nsew')
page_one.grid(row=0,sticky = 'nsew')
page_two.grid(row=0,sticky = 'nsew')
remote_manager_gui.init(remote_manager)
page_one_gui.init(page_one)
page_two_gui.init(page_two)
# END GUI ===========================
# CODE ==============================
frames = {'remote_manager' : remote_manager,
'page_one' : page_one,
'page_two' : page_two,
}
subscribe('SHOW_FRAME',lambda frame_id, frames = frames: frames[frame_id].lift())
publish('SHOW_FRAME','remote_manager')
# END CODE ==========================
Erreicht wird dies dadurch, dass diese Frames mit einer ID in einem Dictionary erfasst werden. Dafür gibt es einen Message Callback, mit dem eine Funktion aufgerufen wird, die dann den entsprechenden Frame liftet. Diese Funktion ist das lambda im subscribe Callback.
Dann hat man diese drei Frames, die sich auch auf Buttondruck gegenseitig liften. Der Code Part dazu ist relativ einfach.
remote_manager_gui.py
Code: Alles auswählen
import tk
from eventbroker import publish
from functools import partial
def init(self):
# GUI ==============================
label =tk.Label(self,text='Willkommen im Remote Manager')
button_page_one = tk.Button(self,name='button_page_one',text='Benutzereinstellungen', width=18)
label_2 = tk.Label(self)
button_2 = tk.Button(self,text='Bildschirmeinstellungen', width=18)
label_3 = tk.Label(self)
button_page_two = tk.Button(self,name='button_page_two',text='Servereinstellungen', width=18)
label_4 = tk.Label(self)
label.pack(pady=15, padx=25)
button_page_one.pack()
label_2.pack(pady=1, padx=25)
button_2.pack()
label_3.pack(pady=1, padx=25)
button_page_two.pack()
label_4.pack(pady=5, padx=25)
# END GUI ===========================
# CODE ==============================
button_page_one.config(command=partial(publish,'SHOW_FRAME','page_one'))
button_page_two.config(command=partial(publish,'SHOW_FRAME','page_two'))
# END CODE ==========================
Code: Alles auswählen
import tk
from eventbroker import publish
from functools import partial
def init(self):
# GUI ==============================
label = tk.Label(self,text='Page One!!!', font='Verdana 12')
button_remote_manager = tk.Button(self,name = 'button_remote_manager',text='Back to Home')
button_page_two = tk.Button(self,name='button_page_two',text='Page Two')
label.pack(pady=20, padx=10)
button_remote_manager.pack()
button_page_two.pack()
# END GUI ===========================
# CODE ==============================
button_remote_manager.config(command=partial(publish,'SHOW_FRAME','remote_manager'))
button_page_two.config(command=partial(publish,'SHOW_FRAME','page_two'))
# END CODE ==========================
Code: Alles auswählen
import tk
from eventbroker import publish
from functools import partial
def init(self):
# GUI ==============================
label = tk.Label(self,text='Page Two!!!', font='Verdana 12')
button_remote_manager = tk.Button(self,name = 'button_remote_manager',text='Back to Home')
button_page_one = tk.Button(self,name='button_page_one',text='Page One')
label.pack(pady=10, padx=10)
button_remote_manager.pack()
button_page_one.pack()
# END GUI ===========================
# CODE ==============================
button_remote_manager.config(command=partial(publish,'SHOW_FRAME','remote_manager'))
button_page_one.config(command=partial(publish,'SHOW_FRAME','page_one'))
# END CODE ==========================
main_menu_gui.py
Code: Alles auswählen
import tk
import manager_menu_gui
import hilfe_menu_gui
def init(self):
# GUI ==============================
manager_menu = tk.Menu(self,name='manager_menu')
hilfe_menu = tk.Menu(self,name='hilfe_menu')
self.add_cascade(menu=manager_menu,label='Manager')
self.add_cascade(menu=hilfe_menu,label='Hilfe')
manager_menu_gui.init(manager_menu)
hilfe_menu_gui.init(hilfe_menu)
# END GUI ===========================
Das ist dann das Untermenü mit viel Action.
manager_menu_gui.py
Code: Alles auswählen
from functools import partial
from eventbroker import publish
def init(self):
# GUI ==============================
self.config(tearoff=0)
self.add_command(label='Komplettes Setup')
self.add_separator()
self.add_command(label='Benutzereinstellungen')
self.add_command(label='Bildschirmeinstellungen')
self.add_command(label='Servereinstellungen')
self.add_separator()
self.add_command(label='Beenden')
remote_manager_index = 0
page_one_index = 2
page_two_index = 4
# END GUI ===========================
# CODE ==============================
self.entryconfig(remote_manager_index,command=partial(publish,'SHOW_FRAME','remote_manager'))
self.entryconfig(page_one_index,command=partial(publish,'SHOW_FRAME','page_one'))
self.entryconfig(page_two_index,command=partial(publish,'SHOW_FRAME','page_two'))
# END CODE ==========================
hilfe_menu_gui.py
Code: Alles auswählen
def init(self):
# GUI ==============================
self.config(tearoff=0)
self.add_command(label='Info')
# END GUI ===========================
Ach so das war es auch schon, denn in application.py war doch nichts zu tun.
- noisefloor
- User
- Beiträge: 4158
- Registriert: Mittwoch 17. Oktober 2007, 21:40
- Wohnort: WW
- Kontaktdaten:
Hallo,
ich fühle mich gerade mit meiner Vermutung mit dem Paralleluniversum unglaublich bestätigt *SCNR*
Gruß, noisefloor
ich fühle mich gerade mit meiner Vermutung mit dem Paralleluniversum unglaublich bestätigt *SCNR*
Gruß, noisefloor
-
- User
- Beiträge: 1715
- Registriert: Freitag 31. Juli 2015, 13:34
Nö, das ist nicht das Paralleluniversum. Das Paralleluniversum ist DynTkInter, dort kann man so etwas noch besser machen:noisefloor hat geschrieben:Hallo,
ich fühle mich gerade mit meiner Vermutung mit dem Paralleluniversum unglaublich bestätigt *SCNR*
Gruß, noisefloor
Code: Alles auswählen
import tk
import lift_frame_gui
import main_menu_gui
def init(self):
# GUI ==============================
lift_frame = tk.Frame(self,name='lift_frame')
main_menu = tk.Menu(self,name='main_menu')
self['menu'] = main_menu
lift_frame.pack(fill='both', expand=1)
lift_frame_gui.init(lift_frame)
main_menu_gui.init(main_menu)
# END GUI ===========================
- import braucht es nicht
- master braucht es nicht
- daher braucht es keine init Funktion
- widget Referen braucht es oft auch nicht
- und über Modulimport ein init in einem Modul aufrufen braucht es auch nicht. Gibt ja auch kein init dort
Das obige sieht in DynTkInter so aus:
Code: Alles auswählen
Frame('lift_frame',link='lift_frame_gui')
pack(fill='both', expand=1)
Menu('main_menu',link='main_menu_gui').select_menu()
Und so ein Script verhält sich gegenteilig wie ein Modul. Ein Modul importiert man und kann auf dieses zugreifen. Aber wenn man so ein Script lädt, dann kann das ladende Modul nicht auf dieses zugreifen, aber das Script auf das Modul. Die globale Ebene des Scriptes ist nämlich die Ebene des Moduls.
-
- User
- Beiträge: 1715
- Registriert: Freitag 31. Juli 2015, 13:34
Läßt sich natürlich auch auf zwei Zeilen reduzieren:
Nö, das mit den Ebenen wie Mainscript stimmt nicht. So ein Script ist ein lokaler Namensraum innerhalb DynTkInter auf den von außen nur die ladende Funktion mittels locals() zugreifen kann.
Code: Alles auswählen
Frame('lift_frame',link='lift_frame_gui').pack(fill='both', expand=1)
Menu('main_menu',link='main_menu_gui').select_menu()
-
- User
- Beiträge: 1715
- Registriert: Freitag 31. Juli 2015, 13:34
Es kommt ja Null darauf an, wie jetzt eine GUI aufgeteilt ist. Man kann sie im Nu ja wieder vereinen.noisefloor hat geschrieben:ich fühle mich gerade mit meiner Vermutung mit dem Paralleluniversum unglaublich bestätigt *SCNR*
Dazu benütze man mein DynTkInter - bitte neueste Version.
Dann ändere man tk.py:
Code: Alles auswählen
'''
try:
from tkinter import *
except ImportError:
from Tkinter import *
'''
from DynTkInter import *
Code: Alles auswählen
import tk
import application_gui
def main():
root = tk.Tk()
application_gui.init(root)
# eigener Code
tk.exportApplication('gui.py')
#root.mainloop()
main()
gui.py
Code: Alles auswählen
# -*- coding: utf-8 -*-
try:
import tkinter as tk
except ImportError:
import Tkinter as tk
#import DynTkInter as tk # for GuiDesigner
# Application definition ============================
class Application(tk.Tk):
def __init__(self,**kwargs):
tk.Tk.__init__(self,**kwargs)
# widget definitions ===================================
self.lift_frame = LiftFrame(self,name='#0_lift_frame')
self.main_menu = MainMenu(self,name='#1_main_menu')
self['menu'] = self.main_menu
self.lift_frame.pack(expand=1, fill='both')
class LiftFrame(tk.Frame):
def __init__(self,master,**kwargs):
tk.Frame.__init__(self,master,**kwargs)
# individual grid definition ===========================
self.rowconfigure(0,weight=1, minsize=0, pad=0)
self.columnconfigure(0,weight=1, minsize=0, pad=0)
# widget definitions ===================================
self.page_one = PageOne(self,name='#2_page_one')
self.page_one.grid(sticky='nesw', row=0)
self.page_two = PageTwo(self,name='#3_page_two')
self.page_two.grid(sticky='nesw', row=0)
self.remote_manager = RemoteManager(self,name='#4_remote_manager')
self.remote_manager.grid(sticky='nesw', row=0)
class PageOne(tk.Frame):
def __init__(self,master,**kwargs):
tk.Frame.__init__(self,master,**kwargs)
# widget definitions ===================================
self.label = tk.Label(self,name='#5_label',text='Page One!!!', font='Verdana 12')
self.button_remote_manager = tk.Button(self,name='#6_button_remote_manager',text='Back to Home')
self.button_page_two = tk.Button(self,name='#7_button_page_two',text='Page Two')
self.label.pack(pady=20, padx=10)
self.button_remote_manager.pack()
self.button_page_two.pack()
class PageTwo(tk.Frame):
def __init__(self,master,**kwargs):
tk.Frame.__init__(self,master,**kwargs)
# widget definitions ===================================
self.label = tk.Label(self,name='#8_label',text='Page Two!!!', font='Verdana 12')
self.button_remote_manager = tk.Button(self,name='#9_button_remote_manager',text='Back to Home')
self.button_page_one = tk.Button(self,name='#10_button_page_one',text='Page One')
self.label.pack(pady=10, padx=10)
self.button_remote_manager.pack()
self.button_page_one.pack()
class RemoteManager(tk.Frame):
def __init__(self,master,**kwargs):
tk.Frame.__init__(self,master,**kwargs)
# widget definitions ===================================
self.label = tk.Label(self,name='#11_label',text='Willkommen im Remote Manager')
self.button_page_one = tk.Button(self,name='#12_button_page_one',text='Benutzereinstellungen', width=18)
self.label_2 = tk.Label(self,name='#13_label_2')
self.button = tk.Button(self,name='#14_button',text='Bildschirmeinstellungen', width=18)
self.label_3 = tk.Label(self,name='#15_label_3')
self.button_page_two = tk.Button(self,name='#16_button_page_two',text='Servereinstellungen', width=18)
self.label_4 = tk.Label(self,name='#17_label_4')
self.label.pack(pady=15, padx=25)
self.button_page_one.pack()
self.label_2.pack(pady=1, padx=25)
self.button.pack()
self.label_3.pack(pady=1, padx=25)
self.button_page_two.pack()
self.label_4.pack(pady=5, padx=25)
class MainMenu(tk.Menu):
def __init__(self,master,**kwargs):
tk.Menu.__init__(self,master,**kwargs)
# widget definitions ===================================
self.manager_menu = ManagerMenu(self,name='#19_manager_menu',tearoff=0)
self.dyntk_name = 'cascade'
self.add_cascade(menu=self.manager_menu,label='Manager')
self.hilfe_menu = HilfeMenu(self,name='#21_hilfe_menu',tearoff=0)
self.dyntk_name = 'cascade'
self.add_cascade(menu=self.hilfe_menu,label='Hilfe')
# indexes for entryconfig later
self.cascade_index = 1
self.cascade_index = 2
class ManagerMenu(tk.Menu):
def __init__(self,master,**kwargs):
tk.Menu.__init__(self,master,**kwargs)
self.config(tearoff=0)
# widget definitions ===================================
self.dyntk_name = 'command'
self.add_command(label='Komplettes Setup')
self.dyntk_name = 'separator'
self.add_separator()
self.dyntk_name = 'command'
self.add_command(label='Benutzereinstellungen')
self.dyntk_name = 'command'
self.add_command(label='Bildschirmeinstellungen')
self.dyntk_name = 'command'
self.add_command(label='Servereinstellungen')
self.dyntk_name = 'separator'
self.add_separator()
self.dyntk_name = 'command'
self.add_command(label='Beenden')
# indexes for entryconfig later
self.command_index = 0
self.separator_index = 1
self.command_index = 2
self.command_index = 3
self.command_index = 4
self.separator_index = 5
self.command_index = 6
class HilfeMenu(tk.Menu):
def __init__(self,master,**kwargs):
tk.Menu.__init__(self,master,**kwargs)
self.config(tearoff=0)
# widget definitions ===================================
self.dyntk_name = 'command'
self.add_command(label='Info')
# indexes for entryconfig later
self.command_index = 0
if __name__ == '__main__':
#Application().mainloop('guidesigner/Guidesigner.py') # for GuiDesigner
Application().mainloop()
-
- User
- Beiträge: 1715
- Registriert: Freitag 31. Juli 2015, 13:34
Attribute sollte man nehmen. Widgets sind ja Objekte kann man also Attribute hinzufügen.
Wenn man seinen Code schreibt ohne Attribute zu nehmen und wenn man dann seine GUI in Klassen konvertiert, dann paßt nämlich der Code nicht mehr zu den generierten Attributen.
Wenn man allerdings nicht vor hat, seinen Code in Klassen zu konvertieren, dann kann man das auch sein lassen.
Wenn man seinen Code schreibt ohne Attribute zu nehmen und wenn man dann seine GUI in Klassen konvertiert, dann paßt nämlich der Code nicht mehr zu den generierten Attributen.
Wenn man allerdings nicht vor hat, seinen Code in Klassen zu konvertieren, dann kann man das auch sein lassen.
-
- User
- Beiträge: 1715
- Registriert: Freitag 31. Juli 2015, 13:34
Ohne Klassen. Attribute, Methoden und Namen hat man ein Höchstmaß an Kapselung!
Die Gliederung in Module ist angebracht bei komplexen großen GUIs. Da kann man Klassen verwenden oder auch nicht. Denn ein Widget anlegen und dann eine init Funktion in einem anderen Modul aufrufen geht genauso gut. Und bietet einen großen Vorteil.
Es existiert eine reine tkinter GUI ohne zusätzlich Verweise über Attributnamen und Widgetnamen - die sollte man dann auch nicht nehmen. Über einen benannten Objektbaum zugreifen kann man dann nicht. Über die Children Liste von tkinter zugreifen, bringt auch nichts, da mit nichtssagenden Objektreferenzen nichts anzufangen ist. Wenn keine zusätzlichen Attribute verwendet werden und auch keine Methoden sind auch darüber keine Zugriffe von außen möglich. Denn auf das Innere von Closures gibt es nur Zugriffe mittels im Closure vereinbarten Callbacks, also Command Callbacks, Event Callbacks, Message Callbacks.
Damit ist dann ein Höchstmaß an Kapselung erreicht und damit ist kreuz und quer Programmierung nicht mehr möglich - sondern Aufrufe gibt es dann nur mehr über wohl definierte Message Interfaces. Eine komplexe GUI sollte dann auch ohne Probleme leicht zu programmieren sein.
Die Gliederung in Module ist angebracht bei komplexen großen GUIs. Da kann man Klassen verwenden oder auch nicht. Denn ein Widget anlegen und dann eine init Funktion in einem anderen Modul aufrufen geht genauso gut. Und bietet einen großen Vorteil.
Es existiert eine reine tkinter GUI ohne zusätzlich Verweise über Attributnamen und Widgetnamen - die sollte man dann auch nicht nehmen. Über einen benannten Objektbaum zugreifen kann man dann nicht. Über die Children Liste von tkinter zugreifen, bringt auch nichts, da mit nichtssagenden Objektreferenzen nichts anzufangen ist. Wenn keine zusätzlichen Attribute verwendet werden und auch keine Methoden sind auch darüber keine Zugriffe von außen möglich. Denn auf das Innere von Closures gibt es nur Zugriffe mittels im Closure vereinbarten Callbacks, also Command Callbacks, Event Callbacks, Message Callbacks.
Damit ist dann ein Höchstmaß an Kapselung erreicht und damit ist kreuz und quer Programmierung nicht mehr möglich - sondern Aufrufe gibt es dann nur mehr über wohl definierte Message Interfaces. Eine komplexe GUI sollte dann auch ohne Probleme leicht zu programmieren sein.
-
- User
- Beiträge: 1715
- Registriert: Freitag 31. Juli 2015, 13:34
Natürlich spricht nichts dagegen im inneren der Closures auch Klassen einzusetzen oder statt der Closure ein referenzloses Objekt, denn da kommt man auch von außen nicht ran.
-
- User
- Beiträge: 1715
- Registriert: Freitag 31. Juli 2015, 13:34
Ich bin aber schon sehr frühzeitig darauf gekommen, wie man in Python gut kapseln kann. Wenn man Methoden von Objekten in Callbacks referenziert und das Objekt selber nirgends, dann bleibt das Objekt im Speicher aber Zugriff von außen gibt es keinen. Die Referenz auf den Callback mag man zwar herausbekommen aber den kann man auch auf die spezifizierte Art und Weise aufrufen das Objekt selber bekommt man aber nicht. Und wenn man dann den Callback löscht, etwa im Eventbroker für die Message einen anderen einträgt, ist das Objekt weg im Garbage Collektor. Und wenn man die Source für die Erzeugung des Objektes nicht in einem Modul hat, sondern das Objekt durch Scriptausführung erzeugt hat - aber nicht Mainscript, ist auch vom Code im Speicher nichts mehr da. Bei einem Widget wäre natürlich das Widget noch da, solange man kein destroy ausführt.Sirius3 hat geschrieben:Man sollte hier im Forum eine Ab-18-Kategorie einführen, nicht dass das jemand liest, der noch nicht 18 Jahr Pythonerfahrung hat und bleibende Schäden davonträgt.
Ich finde Objekte gut, auf die man nicht zugreifen kann und die man spurlos beseitigen kann und den Code im Speicher dazu auch.
Man könnte also eine GUI schreiben mit zigtausenden von Screens mit soviel Python Code, wie die Festplatte hergibt. Aber wenn man immer nur einen Screen im Speicher hat, ist alles kein Problem.
Ist doch ganz einfach: eine lokal aufgerufene Funktion oder Klasse wird durch Bindung einer ihrer Mehoden oder Funktionen an einen Callback zu einem weiter bestehenden Objekt. Auch eine Closure ist dann so ein Objekt.
Zuletzt geändert von Alfons Mittelmeyer am Dienstag 22. August 2017, 12:22, insgesamt 1-mal geändert.
Ich betrachte Programmieren auch als Kunst. Da gibt es realistische, abstrakte bis abartige Werke. Ich schlage vor in unserem Forum ein neues Subforum zu eröffnet, welches als Gallerie für abweichend Werke dient. Bin mir sicher, dass sich jenes Subforum innert kürzester Zeit mit künstlerisch Beiträgen aufblähen wird.Sirius3 hat geschrieben:Man sollte hier im Forum eine Ab-18-Kategorie einführen, nicht dass das jemand liest, der noch nicht 18 Jahr Pythonerfahrung hat und bleibende Schäden davonträgt.
Gruss wuf

Take it easy Mates!
-
- User
- Beiträge: 1715
- Registriert: Freitag 31. Juli 2015, 13:34
Findest Du meine Ideen abartig? Ich habe doch einen Weg gefunden wie man gut kapseln kann. Dafür kann man auch Klassen einsetzen. Die Methoden und Attribute von Klassen sind öffentlich. Aber wenn das Objekt nicht öffentlich ist, sind sie es auch nicht und so kann man gut kapseln:wuf hat geschrieben:Ich betrachte Programmieren auch als Kunst. Da gibt es realistische, abstrakte bis abartige Werke.
Gruss wuf
Code: Alles auswählen
# statt
self.my_frame = MyFrame(self,**kwargs)
self.my_frame.pack()
# schreibe man einfach
MyFrame(self,**kwargs).pack()
# und schon hat man gut gekapselt
- noisefloor
- User
- Beiträge: 4158
- Registriert: Mittwoch 17. Oktober 2007, 21:40
- Wohnort: WW
- Kontaktdaten:
Hallo,
2. Wahre Genies werden zu Lebzeiten oft verkannt -> es gibt also noch die Hoffnung der späten Ehre für dich
Gruß, noisefloor
1. Genie und Wahnsinn liegen dicht beiander.Findest Du meine Ideen abartig? Ich habe doch einen Weg gefunden wie man gut kapseln kann.
2. Wahre Genies werden zu Lebzeiten oft verkannt -> es gibt also noch die Hoffnung der späten Ehre für dich

Gruß, noisefloor
-
- User
- Beiträge: 1715
- Registriert: Freitag 31. Juli 2015, 13:34
Wäre schön, übrigens ist kaum ein Unterschied zwischen Klassen und Funktionen, denn auch Funktionen können Attribute haben:noisefloor hat geschrieben:2. Wahre Genies werden zu Lebzeiten oft verkannt -> es gibt also noch die Hoffnung der späten Ehre für dich
Code: Alles auswählen
def function(*args,**kwargs):
class Attributes:
pass
self = Attributes()
self.a = 5
def output():
print(self.a)
def set_a(value):
self.a = value
# statt __init__(self), braucht man bei Funktionen nicht
output()
set_a(8)
output()
function()
-
- User
- Beiträge: 1715
- Registriert: Freitag 31. Juli 2015, 13:34
Funktionen kann man auch instanzieren. Im nachfolgenden Beispiel legen wir zwei Instanzen einer Funktion an und testen deren Interface
Code: Alles auswählen
class EventBroker():
def __init__(self):
self._dictionary_ = {}
def subscribe(self,message_id,callback):
self._dictionary_[message_id] = callback
def publish(self,message_id,*args,**kwargs):
self._dictionary_[message_id](*args,**kwargs)
eventbroker = EventBroker()
publish = eventbroker.publish
subscribe = eventbroker.subscribe
def function(function_id,message_id):
def output(message):
print(function_id,message)
# callback interface
subscribe(message_id,output)
# hier legen wir zwei Instanzen der Funktion an
function('Funktion 1','func1')
function('Funktion 2','func2')
# hier testen wir deren Interface
publish('func1','Guten Morgen')
publish('func2','Gute Nacht')
Zuletzt geändert von Alfons Mittelmeyer am Dienstag 22. August 2017, 15:16, insgesamt 1-mal geändert.
@Alfons Mittelmeyer: Du verwechselst hier Kapselung mit Zugriffsschutz. Kapseln kann man genau so gut mit Klassen, *und* das ist der in Python vorgesehene Weg. Wenn man mehr Zugriffsschutz will, dann will man eine andere Programmiersprache verwenden.
Das `function()`-Beispiel macht keinen Sinn. Da ist nichts wofür man eine Klasse bräuchte.
Zudem haben diese lokalen Funktionen den Nachteil das man sie nicht isoliert testen kann, weder zur Fehlersuche, noch in Unit-Tests.
Das `function()`-Beispiel macht keinen Sinn. Da ist nichts wofür man eine Klasse bräuchte.
Zudem haben diese lokalen Funktionen den Nachteil das man sie nicht isoliert testen kann, weder zur Fehlersuche, noch in Unit-Tests.