wieder mal oop

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.
Gast

wieder mal oop

Beitragvon Gast » Dienstag 29. März 2005, 22:23

hallo,

passt denke ich schon hierher,

also lassen sich die anweisungen die ich im konstruktor stehen habe auch als klassenattribute definieren?

Code: Alles auswählen

class Fenster:


    #Abstand der Elemente
    a_x=5 #Abstand horizontal
    a_y=5 #Abstand vertikal

    #Die Buttons bekommen alle dieselbe Breite
    b=20

    #Farbe wird auch von la verwendet
    f="#00ff00"

    lt=""

   
    def __init__(self):
       
   
        self.root.wm_geometry('+20+20')
        self.root.resizable(0,0)

        self.root.protocol("WM_DELETE_WINDOW",self.mainexit)
       

        self.la=Label(self.root,bg=self.f,text="///GARO_GUI")
        self.la.grid(row=0,column=0,
                     columnspan=2,
                     padx=self.a_x,pady=self.a_y)
     
        self.la_1=Label(self.root,bg=self.f,text=self.lt)
        self.la_1.grid(row=1,column=0,
                       columnspan=2,
                       padx=self.a_x,pady=self.a_y)
       
        self.button=Button(self.root,
                           text="Prog. Beenden",
                           width=10,command=self.ende)
        self.button.grid(row=15,column=0,
                         columnspan=2,
                         padx=10,pady=10)


mfg

rolgal
Benutzeravatar
Leonidas
Administrator
Beiträge: 16023
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Beitragvon Leonidas » Dienstag 29. März 2005, 22:53

WIe wärs mit einem Beispiel:

Code: Alles auswählen

class I(object):
    a = "Class"
    def __init__(self):
        self.a = "Instance"

Somit kannst du auf I.a zugreifen, wobei du auf den Wert a der Klasse I zugreifst (="Class"), oder wenn du eine Instanz i der Klasse I erstellst auf i.a, was dir den Wert "Instance" gibt.
My god, it's full of CARs! | Leonidasvoice vs Modvoice
Gast

Beitragvon Gast » Dienstag 29. März 2005, 23:02

hi leonidas,

ist mir völlig klar dein beispiel.

aber wie soll ich das in meinem fall verwenden?

ich hätte gern alles was jetzt im konstruktor steht als klassenattribute, falls das geht.

der konstruktor wird dann gar nicht mehr aufgerufen.

in meinem konkreten fall könnte das von vorteil sein.

mfg

rolgal
Benutzeravatar
Leonidas
Administrator
Beiträge: 16023
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Beitragvon Leonidas » Mittwoch 30. März 2005, 00:00

Du kannst es einfach mal versuchen und gucken ob es geht (ich kann es grad nicht, weil dein Code irgendwie unvollständig ist.. halt pseudocode). Das Problem könnte höhstens sein, dass du dann in allen Instanzen der Klasse die eine Referenz auf jeweils immer die gleichen Objekte. Wie gesagt: du kannst es probieren, gucken was geht und fertig. Ich wüsste aber nicht, wo ein Vorteil sein könnte, Klassen ohne Konstruktor zu haben.
My god, it's full of CARs! | Leonidasvoice vs Modvoice
Gast

Beitragvon Gast » Mittwoch 30. März 2005, 00:44

was ja momentan, meiner meinung, nach unglücklich ist, ist die tatsache, dass der konstruktor der klasse Fenster ja einen fehler auslöst, sollte eine Instanz von Fenster aufgerufen werden.

meine überlegung war daher, alles was im konstruktor steht als klassenattribute zu definieren.
nur wie müsste es dann z. b. statt

Code: Alles auswählen

self.root.resizable(0,0)
heissen?
diese anweisung gilt für alle fenster, die von der klasse Fenster abgeleitet werden. dasselbe gilt für den rest.

was ich nicht will: einen konstruktor der so wie er jetzt ist keiner ist, und andererseits will ich das was im konstruktor steht net in jeder anderen klasse anführen.

die idee von abstrakten klassen find ich nicht so übel im allgemeinen.


verstehst mein anliegen?

mfg

rolgal
Benutzeravatar
Leonidas
Administrator
Beiträge: 16023
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Beitragvon Leonidas » Mittwoch 30. März 2005, 07:20

rolgal hat geschrieben:was ja momentan, meiner meinung, nach unglücklich ist, ist die tatsache, dass der konstruktor der klasse Fenster ja einen fehler auslöst, sollte eine Instanz von Fenster aufgerufen werden.

Das liegt, so wie ich das sehe daran, dass bei dir self.root nicht definiert ist. Aber da kann self.root sonstwo stehen, ob in Konstruktor oder nicht, man kann auf self.root nicht zugreifen.

Also, erstmal deinen Konstruktor-Code ausbügeln, so dass er läuft:

Code: Alles auswählen

import Tkinter as tk
class Fenster:
    #Abstand der Elemente
    a_x=5 #Abstand horizontal
    a_y=5 #Abstand vertikal

    #Die Buttons bekommen alle dieselbe Breite
    b=20

    #Farbe wird auch von la verwendet
    f="#00ff00"

    lt=""

    def __init__(self):
        self.root = tk.Tk()
        self.root.wm_geometry('+20+20')
        self.root.resizable(0,0)

        self.root.protocol("WM_DELETE_WINDOW",self.mainexit)
       

        self.la=tk.Label(self.root,bg=self.f,text="///GARO_GUI")
        self.la.grid(row=0,column=0,
                     columnspan=2,
                     padx=self.a_x,pady=self.a_y)
     
        self.la_1=tk.Label(self.root,bg=self.f,text=self.lt)
        self.la_1.grid(row=1,column=0,
                       columnspan=2,
                       padx=self.a_x,pady=self.a_y)
       
        self.button=tk.Button(self.root,
                           text="Prog. Beenden",
                           width=10,command=self.ende)
        self.button.grid(row=15,column=0,
                         columnspan=2,
                         padx=10,pady=10)
        self.root.mainloop()
   
    mainexit, ende = [lambda x: 0] * 2

Fenster()

Das das Fenster nicht zugeht ist mir jetzt herzlich egal, es ist ja nur zu demonstrationszwecken.

Und jetzt nochmal der Code als Klassenglobale Sache:

Code: Alles auswählen

import Tkinter as tk
class Fenster:
    #Abstand der Elemente
    a_x=5 #Abstand horizontal
    a_y=5 #Abstand vertikal

    #Die Buttons bekommen alle dieselbe Breite
    b=20

    #Farbe wird auch von la verwendet
    f="#00ff00"

    lt=""
   
    ende = [lambda: 0]
    def mainexit(*args):
        pass
   
    root = tk.Tk()
    root.wm_geometry('+20+20')
    root.resizable(0, 0)
    root.protocol("WM_DELETE_WINDOW", mainexit)
   
    la = tk.Label(root, bg=f, text="///GARO_GUI")
    la.grid(row=0,column=0,
                     columnspan=2,
                     padx=a_x,pady=a_y)
                     
    la_1 = tk.Label(root, bg=f, text=lt)
    la_1.grid(row=1,column=0,
                       columnspan=2,
                       padx=a_x,pady=a_y)
       
    button=tk.Button(root,
                        text="Prog. Beenden",
                        width=10, command=ende)
    button.grid(row=15,column=0,
                        columnspan=2,
                        padx=10,pady=10)
   

win = Fenster()
win.root.mainloop()

Ist ja kein Problem das so zu machen.
My god, it's full of CARs! | Leonidasvoice vs Modvoice
Gast

Beitragvon Gast » Mittwoch 30. März 2005, 12:06

hi leonidas,


Das liegt, so wie ich das sehe daran, dass bei dir self.root nicht definiert ist. Aber da kann self.root sonstwo stehen, ob in Konstruktor oder nicht, man kann auf self.root nicht zugreifen.


das ist mir klar, self.root muss entweder im konstruktor oder auch im klassenglobalen raum definiert werden.
(ich finde es sinnvoll anzuführen, wenn etwas schon klar ist, da ich glaube, dass der dialog effizienter wird)

zuerst mal vielen dank für die beispiele, da ist wieder viel cooles pythonzeug drin, das ich so nicht kannte, dazu aber später mehr, wenn du dann noch lust hast, grins

du kennst vielleicht diesen thread hier:

http://python.sandtner.org/viewtopic.php?t=3005

es stellte sich schlussendlich heraus: will ich diese lösung haben, dass das suchfenster als eigene klasse existiert, muss self.root auf jeden fall übergeben werden beim aufruf.

und das mit dem übergeben klappt offensichtlich nur, wenn self.root=Tk() erst im konstruktor von HauptFenster aufgerufen wird, der ersten nicht abstrakten klasse
früher stand self.root=Tk() auch im konstruktor von Fenster. der konstruktor von Fenster wurde immer zuerst ausgeführt, dann der Konstruktor der betreffenden klasse.

auch wenn es viel ist, doch mal den code, keine sorge, er ist eh gekürzt


:lol:

Code: Alles auswählen

class Fenster:


    #Abstand der Elemente
    a_x=5 #Abstand horizontal
    a_y=5 #Abstand vertikal

    #Die Buttons bekommen alle dieselbe Breite
    b=20

    #Farbe wird auch von la verwendet
    f="#00ff00"

    lt=""
   

   
    def __init__(self):
       

        self.root.wm_geometry('+20+20')
        self.root.resizable(0,0)

        self.root.protocol("WM_DELETE_WINDOW",self.mainexit)

        self.la=Label(self.root,bg=self.f,text="///GARO_GUI")
        self.la.grid(row=0,column=0,
                     columnspan=2,
                     padx=self.a_x,pady=self.a_y)
     
        self.la_1=Label(self.root,bg=self.f,text=self.lt)
        self.la_1.grid(row=1,column=0,
                       columnspan=2,
                       padx=self.a_x,pady=self.a_y)
       
        self.button=Button(self.root,
                           text="Prog. Beenden",
                           width=10,command=self.ende)
        self.button.grid(row=15,column=0,
                         columnspan=2,
                         padx=10,pady=10)


    def ende(self):

        antwort=tkMessageBox.askyesno\
                 ("Warnung","Sicher beenden?")
        if antwort==1:
            sys.exit(0)


    def mainexit(self):
       
        self.root.withdraw()

   
   
 
class HauptFenster(Fenster):

    lt="Ausgabe"

       
    def __init__(self,host,user,db,db_table,passwd=''):


        self.root=Tk()

       #bin nich darufgekommen, wie ich hier schon self.root=Toplevel(root) verwenden könnte

        Fenster.__init__(self)
       
        #jetzt kann auf self.root auch im konstruktor von Fenster aufgerufen werden

        self.root.title("Hauptfenster")
         
        self.database=DataBase(host,user,db,db_table,passwd)

        self.db_table=db_table

       
        self.choice=StringVar()
        self.cols_names=[]

        self.scb=Scrollbar(self.root, orient="vertical")

        self.li_1=Listbox(self.root,
                          width=50,height=8,
                          yscrollcommand=self.scb.set)
       
        self.scb["command"]=self.li_1.yview
       
        self.li_1.grid(row=2,column=0,
                       columnspan=2,
                       padx=self.a_x,pady=self.a_y)
       
        self.scb.grid(row=2,column=2,padx=self.a_x,pady=self.a_y)

        self.b_1=Button(self.root,width=self.b,text="Alle Daten",
                        command=lambda:
                        self.list_data
                        (result=self.database.get_data
                        ("select * from %s "%self.db_table)))

                       
        self.b_1.grid(row=3,column=0,padx=self.a_x,pady=self.a_y)
       

        self.b_2=Button(self.root,width=self.b,
                        text="Loeschen",command=self.ask)
        self.b_2.grid(row=3,column=1,padx=self.a_x,pady=self.a_y)
       
       
        self.b_3=Button(self.root,width=self.b,text="Sortieren",
                        command=lambda:
                        self.list_data
                        (result=self.database.get_data
                        ("select * from %s order by %s"%(self.db_table,self.choice.get()))))
        self.b_3.grid(row=4,column=0,padx=self.a_x,pady=self.a_y)
       

        self.b_4=Button(self.root,width=self.b,text="Eingabe")#gekürzt

        self.b_4.grid(row=4,column=1,padx=self.a_x,pady=self.a_y)


        self.b_5=Button(self.root,width=self.b,text="Suchen",
                        command=lambda:SuchFenster(self,self.root,self.database,self.db_table))

       #hier wird also self.root übergeben. und dann klappt es auch, dass im suchfenster
       #die werte der radiobuttons zurückgegeben werden

        self.b_5.grid(row=5,column=0,padx=self.a_x,pady=self.a_y)
       

        self.b_6=Button(self.root,width=self.b,text="Bearbeiten")
        self.b_6.grid(row=5,column=1,padx=self.a_x,pady=self.a_y)

        for elements in self.database.db_table_cols:
             self.cols_names.append(elements[0])       

        for i in range(len(self.cols_names)):

            self.rb=Radiobutton(self.root,text=self.cols_names[i],
                        value=self.cols_names[i],
                        variable=self.choice)
            self.rb.grid(row=i+6,column=1,padx=self.a_x,pady=self.a_y)

        self.list_data(result=self.database.get_data("select * from %s"%self.db_table))


    def list_data(self,result):
       
        self.li_1.delete(0,END)
        for elements in result:
            self.li_1.insert("end",elements)
           

    def get_selected(self,action):

        choice=self.li_1.get("active")
        choice=str(choice[0])
        action=action%choice
        return action
   

    def ask(self):

        answer=tkMessageBox.askyesno("Warnung",
                                     "Wollen Sie den gewaehlten Datensatz sicher loeschen ?")
        if answer==1:
            self.database.set_data(action=self.get_selected("delete from %s where %s = %s"%(self.db_table,
                                             self.database.db_table_cols[0][0],
                                             "%s")))
        else:
            pass



class SuchFenster(Fenster):

    lt="Suche"


    def __init__(self,hf,root,database,db_table):

        self.root=Toplevel(root)

        self.root.title("Suchfenster")
       
        Fenster.__init__(self)

        self.choice=StringVar()
        self.database=database
        self.db_table=db_table
        self.cols_names=[]

        for elements in self.database.db_table_cols:
            self.cols_names.append(elements[0])

        self.entry=Entry(self.root)
        self.entry.grid(row=3,column=0)

        for i in range(len(self.cols_names)):

            self.rb=Radiobutton(self.root,text=self.cols_names[i],
                        value=self.cols_names[i],
                        variable=self.choice)
            self.rb.grid(row=i+2,column=1,padx=self.a_x,pady=self.a_y)
           

        self.b_1=Button(self.root,text="Suche",
                        command=lambda:
                        hf.list_data
                        (result=self.database.get_data
                        ("select * from %s where %s = '%s'"%(self.db_table,self.choice.get(),self.entry.get()))))
        self.b_1.grid(row=9,column=0)

if __name__ == "__main__":

    hf=HauptFenster("localhost","rolgal","crossover","user","mag.art.")
    mainloop()



so funktioniert alles, nur eben hat jetzt Fenster einen konstruktor der eigentlich keiner ist, die frage ist, ob das wurscht ist oder ob man das auf jeden fall beheben sollte.

wenn man es behebt, sehe ich 2 möglichkeiten:
entweder kann ich bereitss in HauptFenster self.root=Toplevel(root) verwenden, ohne, dass komische dinge passieren oder self.root=irgendwas kann in irgendeiner form in Fenster geschrieben werden ohne, dass es mir probleme bereitet.

so, ich hoffe ich konnte das einigermaßen verständlich darlegen, wenn nicht, dann bitte nein posten, ich werde dann über edit versuchen solange den beitrag zu bearbeiten bis er verständlich ist.

mfg

rolgal
Benutzeravatar
Leonidas
Administrator
Beiträge: 16023
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Beitragvon Leonidas » Mittwoch 30. März 2005, 13:46

rolgal hat geschrieben:zuerst mal vielen dank für die beispiele, da ist wieder viel cooles pythonzeug drin, das ich so nicht kannte, dazu aber später mehr, wenn du dann noch lust hast, grins

Klar, gerne.

rolgal hat geschrieben:auch wenn es viel ist, doch mal den code, keine sorge, er ist eh gekürzt

Hm, wäre besser wenn du den Code so postest das der auch Out-of-the-box läuft, denn hier fehlen die imports und DataBase. Ohne einen funtionsfähigen Beispielcode ist das wirklich nicht besonders nachzuvollziehen (wie wärs mit einem kurzen Minimalbeispiel?).
My god, it's full of CARs! | Leonidasvoice vs Modvoice
Gast

Beitragvon Gast » Mittwoch 30. März 2005, 16:32

hi,

rolgal hat folgendes geschrieben:
zuerst mal vielen dank für die beispiele, da ist wieder viel cooles pythonzeug drin, das ich so nicht kannte, dazu aber später mehr, wenn du dann noch lust hast, grins

Klar, gerne.


super, fein



ok, ich glaube, folgender code ist ideal, hoffe ich zumindest:
minimal ist es nicht, sollte aber laufen und es ist doch sehr am orig. dran.
ist vielleicht doch feiner zum reindenken.


Code: Alles auswählen

#!/usr/bin/python
# -*- coding: utf-8 -*-


from Tkinter import *
from ScrolledText import*
import tkMessageBox
import sys



class Fenster:


    #Abstand der Elemente
    a_x=5 #Abstand horizontal
    a_y=5 #Abstand vertikal

    #Die Buttons bekommen alle dieselbe Breite
    b=20

    #Farbe wird auch von la verwendet
    f="#00ff00"

    lt=""

   
    def __init__(self):
       

        self.root.wm_geometry('+20+20')
        self.root.resizable(0,0)

        self.root.protocol("WM_DELETE_WINDOW",self.mainexit)

        self.la=Label(self.root,bg=self.f,text="///GARO_GUI")
        self.la.grid(row=0,column=0,
                     columnspan=2,
                     padx=self.a_x,pady=self.a_y)
     
        self.la_1=Label(self.root,bg=self.f,text=self.lt)
        self.la_1.grid(row=1,column=0,
                       columnspan=2,
                       padx=self.a_x,pady=self.a_y)
       
        self.button=Button(self.root,
                           text="Prog. Beenden",
                           width=10,command=self.ende)
        self.button.grid(row=15,column=0,
                         columnspan=2,
                         padx=10,pady=10)


    def ende(self):

        antwort=tkMessageBox.askyesno\
                 ("Warnung","Sicher beenden?")
        if antwort==1:
            sys.exit(0)


    def mainexit(self):
       
        self.root.withdraw()

   
   
 
class HauptFenster(Fenster):

    lt="Ausgabe"

       
    def __init__(self):
       

        self.root=Tk()

        Fenster.__init__(self)

        self.root.title("Hauptfenster")

        self.choice=StringVar()

        #für die Besprechung jetzt vorgegebene Werte
        self.cols_names=['id','vorname','name','land','email']

        self.scb=Scrollbar(self.root, orient="vertical")

        self.li_1=Listbox(self.root,
                          width=50,height=8,
                          yscrollcommand=self.scb.set)
       
        self.scb["command"]=self.li_1.yview
       
        self.li_1.grid(row=2,column=0,
                       columnspan=2,
                       padx=self.a_x,pady=self.a_y)
       
        self.scb.grid(row=2,column=2,padx=self.a_x,pady=self.a_y)

        self.b_1=Button(self.root,width=self.b,text="Alle Daten")
        self.b_1.grid(row=3,column=0,padx=self.a_x,pady=self.a_y)
       

        self.b_2=Button(self.root,width=self.b,text="Loeschen")
        self.b_2.grid(row=3,column=1,padx=self.a_x,pady=self.a_y)
       
       
        self.b_3=Button(self.root,width=self.b,text="Sortieren")

        self.b_3.grid(row=4,column=0,padx=self.a_x,pady=self.a_y)
       

        self.b_4=Button(self.root,width=self.b,text="Eingabe")
        self.b_4.grid(row=4,column=1,padx=self.a_x,pady=self.a_y)


        self.b_5=Button(self.root,width=self.b,text="Suchen",
                        command=lambda:SuchFenster(self,self.root))
       #self.root wird also hier übergeben - emöglicht:self.root=Toplevel(root)
       #leider keinen weg gefunden dies schon im HauptFenster zu tun.

        self.b_5.grid(row=5,column=0,padx=self.a_x,pady=self.a_y)
       

        self.b_6=Button(self.root,width=self.b,text="Bearbeiten")
        self.b_6.grid(row=5,column=1,padx=self.a_x,pady=self.a_y)

        for i in range(len(self.cols_names)):

            self.rb=Radiobutton(self.root,text=self.cols_names[i],
                        value=self.cols_names[i],
                        variable=self.choice)
            self.rb.grid(row=i+6,column=1,padx=self.a_x,pady=self.a_y)
           

       
           
class SuchFenster(Fenster):

    lt="Suche"


    def __init__(self,hf,root):

        self.root=Toplevel(root)

        self.root.title("Suchfenster")
       
        Fenster.__init__(self)

        self.choice=StringVar()

        self.entry=Entry(self.root)
        self.entry.grid(row=3,column=0)

        for i in range(len(hf.cols_names)):

            self.rb=Radiobutton(self.root,text=hf.cols_names[i],
                        value=hf.cols_names[i],
                        variable=self.choice)
            self.rb.grid(row=i+2,column=1,padx=self.a_x,pady=self.a_y)
           

        self.b_1=Button(self.root,text="Suche",
                        command=self.get_selected)
       
        self.b_1.grid(row=9,column=0)
       


    def get_selected(self):
        choice=self.choice.get()
        print choice


if __name__ == "__main__":

    hf=HauptFenster()
    mainloop()


der einzige button der was auslöst ist "Suchen" er öffnet ein Fenster, dort kann man einen radiobutton wählen, und erneutes klicken auf "Suche" im SuchFenster gibt den Wert der StringVar() choice zurück.
alles was mit database zu tun hat ist raus, das brauchen wir ja nicht momentan, denke ich.


mfg

rolgal
Benutzeravatar
Leonidas
Administrator
Beiträge: 16023
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Beitragvon Leonidas » Mittwoch 30. März 2005, 19:54

Achh, ich glaube jetzt nach längerem betrachten verstehe ich dein Problem: du meinst, das "Fenster" zwar eine Klasse ist, aber es keinen Sinn macht Instanzen davon zu machen, ohne __init__ zu überschreiben? Da ist mir gleich das Kapitel zu den abstrakten Klassen aus dem "Java ist auch eine Insel"-Buch eingefallen (das Buch ist echt gut, ich mag zwar Java nicht sonderlich, aber wenn ich Java lernen wollte dann mit diesem Buch). Es handelt zwar nicht direkt von Python, aber OOP ist es ja. Python hat ja keine abstrakten Klassen.. deswegen würde ich es folgendermaßen machen: die Sachen aus Fenter.__init__() nach Fenster.prepare() verschieben, und in __init__ nur ein raise NotImplementedError("This is an abstract class, overload __init__ and call prepare()").
My god, it's full of CARs! | Leonidasvoice vs Modvoice
Gast

Beitragvon Gast » Mittwoch 30. März 2005, 20:13

hi,...

Achh, ich glaube jetzt nach längerem betrachten verstehe ich dein Problem: du meinst, das "Fenster" zwar eine Klasse ist, aber es keinen Sinn macht Instanzen davon zu machen, ohne __init__ zu überschreiben?


ich würde sagen ja, aber macht auch sonst keinen sinn, weil Fenster ja nur abstrakt ist, aber wahrscheinlich heisst das in etwa das gleiche :D

Python hat ja keine abstrakten Klassen.


naja, ich habe die idee aus einem python buch (work shop python, addison-wesley), auch dookie stand der idee positiv gegenüber, zumindest habe ich es so in einem persönlichen gespräch mit ihm aufgefasst.

warum denkst du dass es keine abstrakte klassen gibt in python?
frage dies aus ehrlichem interesse (führ ich an um ein missverständnis zu verhindern :D )


deswegen würde ich es folgendermaßen machen: die Sachen aus Fenter.__init__() nach Fenster.prepare() verschieben, und in __init__ nur ein raise NotImplementedError("This is an abstract class, overload __init__ and call prepare()").


äh, das ist mir jetzt doch etwas zu schnell, krieg ich das in einem beispiel bitte?

mfg

rolgal
Benutzeravatar
Leonidas
Administrator
Beiträge: 16023
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Beitragvon Leonidas » Mittwoch 30. März 2005, 20:43

Also so wie ich abstrakte Klassen verstehe, lassen sich davon keine Instanzen erstellen (korrigier mich wenn ich falsch lieg).

Aber in Python ist er eigentlich möglich von jeder Klasse Instanzen zu erstellen, also kann es keine abstrakten Klassen geben, zumindest nicht so wie im Sinne von Java, wo du das Keyword abstract hast und es verhindert von dieser Klasse Instanzen zu bilden (aber Vererbung ist weiterhin kein Problem).
Diese Funktionalität kann man aber mit Python nachbauen (hier kommt das Beispiel):

Code: Alles auswählen

class Fenster(object):
    def __init__(self):
        raise NotImplementedError("Abstract class")
   
    def prepare(self):
        print "Initialisation des Tk Zeugs.. fertig"

class HauptFenster(Fenster):
    def __init__(self):
        self.prepare()
        #sonstiges init-Zeug

HauptFenster()
#Fenster()

Du kannst von Fenster vererben, aber es nicht direkt aufrufen, da __init__ das verhindert. Dafür hat Fenster die Funktion prepare(), wohin du alles was bei dir in Fenster.__init__() steht, verschieben könntest. Aufrufen kannst du aber Hauptfenster, welches ja von Fenster erbt, also prepare() genauso besitzt. Nun wird prepare() von HauptFenster.__init__ aufgerufen, also alles ist in Ordnung.

Oder würdest du das anders lösen? Oder hab ich gar das Problem falsch verstanden?
My god, it's full of CARs! | Leonidasvoice vs Modvoice
Gast

Beitragvon Gast » Mittwoch 30. März 2005, 21:46

hi,...

zu den abstrakten klassen: im sinne von java gibt es das nicht, aber die idee kann imitiert werden, so war es auch in dem buch gemeint, immerhin schreibt der autor selbst, dass er das wort "abstrakt" großzügig verwendet.

besonders in dem beispiel finde ich die idee total gut, eine klasse, die attribute und methoden festhält, die für alle anderen klassen gelten, vererbung wird dadurch oft viel einfacher.


Du kannst von Fenster vererben, aber es nicht direkt aufrufen, da __init__ das verhindert. Dafür hat Fenster die Funktion prepare(), wohin du alles was bei dir in Fenster.__init__() steht, verschieben könntest. Aufrufen kannst du aber Hauptfenster, welches ja von Fenster erbt, also prepare() genauso besitzt. Nun wird prepare() von HauptFenster.__init__ aufgerufen, also alles ist in Ordnung.

Oder würdest du das anders lösen? Oder hab ich gar das Problem falsch verstanden?


ich werde es gleich einbauen, das müsste genau so hinhauen, danke!

noch ne frage: warum verwendest du hier eine new_style klasse?



mfg

rolgal
Gast

Beitragvon Gast » Mittwoch 30. März 2005, 22:02

nochmal ich, die verwendung von (object) führt bei mir zu folgender meldung:

Code: Alles auswählen

Traceback (most recent call last):
  File "/home/rolgal/python/gui_crossoveruserd.py", line 304, in -toplevel-
    class BearbeitungsFenster(Fenster,EingabeFenster):
TypeError: Cannot create a consistent method resolution
order (MRO) for bases EingabeFenster, Fenster


ohne gehts tadellos, finde es mit deiner lösung viel runder und sinniger!

die new_style dinger sind mir allerdings noch net geheuer :D :shock:

grüße

rolgal
Benutzeravatar
Leonidas
Administrator
Beiträge: 16023
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Beitragvon Leonidas » Mittwoch 30. März 2005, 22:06

rolgal hat geschrieben:noch ne frage: warum verwendest du hier eine new_style klasse?

Weil ich New Style Klassen mag, man ist für die Zukunft gerüstet. So kann man properties nutzen, super(), Diamond Rule wird angewendet, (laut Psyco Projekt) bessere Performance (nicht getestet und auch kein wesentlicher Grund für mich).
Natürlich kannst du auch Old-Syle Klassen verwenden wenn du die lieber magst.

Edit: hast du nur Fenster von object erben lassen? Naja,m wenn nicht geht, dann gehts halt nicht, kein Grund sich dan Kopf darüber zu lange zu zerbrechen. Ich sollte mal etwas Doku zu den New-style Klassen schreiben.
My god, it's full of CARs! | Leonidasvoice vs Modvoice

Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder