experimente mit klassen!

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

experimente mit klassen!

Beitragvon Gast » Dienstag 20. April 2004, 09:50

hallo zusammen!

seit kurzem beschäftige ich mich wieder mehr mit oop. und die new style klassen, die dookie uns erklärt hat sind ein scharfes ding. momentan habe ich einfach lust alles mögliche mit neuen und alten klassen auszuprobieren.

angefangen hat alles hier
[url]
http://python.sandtner.net/viewtopic.php?t=1466
[/url]

ob die idee gut ist oder nicht, weiss ich net, auch kann ich eventuelle negative nebenwirkungen net abschätzen, aber funktionieren tut es:


Code: Alles auswählen

#!/usr/local/bin/python


from webtools import *




class Site_a:

    content_type='''Content-Type: text/html

    '''

    general='''<html><head><title>crossoverguitar</title>
    <link rel='stylesheet' type='text/css' href='../../crossover/sheet1.css'></head>
    <body background='../../crossover/_themes/kopie-von-sumi-malerei/sumtextb.jpg'>
    <div align='center'>'''

   
    content='''<h2>Eine dynamisch erstellte Seite</h2>
    <p><a href='http://localhost/crossover/'>...zur&ck zu Crossoverguitar</a></p>'''

    end='''</div></div><p><br><hr color='#990000'>
    <div align='center'>
    <span class='copyright'>©right 2000 roga-verlag ---
    <a href='mailto:rolandgall@weberanto.net' target='inhalt'>rolandgall@weberanto.net</a>
    </span></div></p></body></html>'''


    def __init__(self):
        print self

       
    def __str__(self):
        site=self.content_type+self.general+self.div+self.content+self.end
        return site   




class ErrorSite_a(Site_a):

    content='''<h2>%s</h2>
    <p><a href='javascript:history.back()'>%s</a></p>'''

    def __init__(self,errortype,link):
         
        self.errortype=errortype
        self.link=link
        self.content=self.content%(self.errortype,self.link)
        print self
       
       


class ConfirmationSite_b(Site_a):

    content='''<h2>%s</h2>'''

    def __init__(self,confirmation):

        self.confirmation=confirmation
        self.content=self.content%(self.confirmation)
        print self
       



##
##for myclasses in (Site,ErrorSite):
##    myclasses.divb='''<div style='width:555; margin-top:150px; margin-bottom:125px;'>'''
##
##for myclasses in (ConfirmationSite,TestSite):
##    myclasses.divb='''<div style='width:555; margin-top:100px; margin-bottom:125px;'>'''



k=globals()
l=k.copy()

for i in l:
    instance=l[i]
    if i.endswith('Site_a'):
        instance.div='''<div style='width:555; margin-top:150px; margin-bottom:125px;'>'''
    if i.endswith('Site_b'):
        instance.div='''<div style='width:555; margin-top:100px; margin-bottom:125px;'>'''



if __name__=='__main__':
##    a=Site_a()
    b=ErrorSite_a('Du bist zum Tode verurteilt!','...hier gehts zum Henker')
##   c=ConfirmationSite_b('Danke f&r die tolle Klasse!')


atrribute, die nicht bei allen klassen, aber bei einigen gleich sind, werden dynamisch hinzugefügt. zuerst habe ich das mit 2 schleifen, die auskommentiert sind, ausprobiert, das hat aber den nachteil, dass ich jedesmal eine seite da oder dort einfügen muss.

dann dachte ich mi: ich lass den namenraum auslesen und such dann alle Seiten des Typs a und Typs b, das scheint mir leichter und angenehmer zu warten. ich brauche also nur nuch mir beim definieren überlegen, welcher typ die klasse werden soll.

was meint ihr dazu?

mfg

rolgal
Benutzeravatar
Dookie
Python-Forum Veteran
Beiträge: 2010
Registriert: Freitag 11. Oktober 2002, 18:00
Wohnort: Salzburg
Kontaktdaten:

Beitragvon Dookie » Dienstag 20. April 2004, 11:47

Hi rolgal,

irgendwie bekomme ich bei deiner Lösung, Bauchschmerzen. :?
An bestehenden Klassen bzw Instanzen quasi, von Aussen herumschustern, erscheint mir nicht gerade sauberes OOP.
OOP bedeutet für mich daß Daten und Methoden eng verbunden sind und das Manipulieren der Daten, der Objekte, möglichst über die definierten Schnittstellen (Methoden) zu erfolgen hat.

Bei Deiner Vorgehensweise, nimmst Du den Objekten die Möglichkeit auf die Änderung zu reagieren, was eben einer der Vorteile von OOP ist.

Für diese Problemstellung gibts mindestens 2 elegantere Lösungen.

1. Da du ohnehin 2 Klassen definierst "Site_a" und "Site_b" kannst Du die unterschiedlichen Attribute ja dort definieren, bzw wie bei meinem Beispiel gezeigt, diese Attribute beim erzeugen der Site-Objekte als Keywordparameter mit übergeben an __init__ und dann in der Klasse zuweisen.

2. Bei New-style Klassen gibts auch noch Metaklassen. Dafür könnte man dann aber einen ganzen Pythonkurs machen, der sich mit den Möglichkeiten die Metaklassen bieten befasst. Ist echt schwerer Stoff, den ich selber noch nicht bis ins letzte ausgelotet habe.


Gruß

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

Beitragvon Leonidas » Dienstag 20. April 2004, 13:26

Dookie hat geschrieben:Bei Deiner Vorgehensweise, nimmst Du den Objekten die Möglichkeit auf die Änderung zu reagieren, was eben einer der Vorteile von OOP ist.

Um sowas zu verhindern gibt es ja sowas wie private members in anderen sparchen, wie schauts mit Python aus?
My god, it's full of CARs! | Leonidasvoice vs Modvoice
Benutzeravatar
Dookie
Python-Forum Veteran
Beiträge: 2010
Registriert: Freitag 11. Oktober 2002, 18:00
Wohnort: Salzburg
Kontaktdaten:

Beitragvon Dookie » Dienstag 20. April 2004, 13:32

Hi Leonidas,

in Python kannst Du Attribute mit __ anfangen lassen, dann sind sie nur über Umwege direkt zugreifbar, oder du verwendest New-style Klassen mit Properties, wenn dort nur die get-Methode definiert ist, haben diese auch nur lesezugriff.


Gruß

Dookie
Gast

Beitragvon Gast » Dienstag 20. April 2004, 16:43

hallo dookie!


irgendwie bekomme ich bei deiner Lösung, Bauchschmerzen.

sorry wegen der bauchschmerzen :wink: .
An bestehenden Klassen bzw Instanzen quasi, von Aussen herumschustern, erscheint mir nicht gerade sauberes OOP.
OOP bedeutet für mich daß Daten und Methoden eng verbunden sind und das Manipulieren der Daten, der Objekte, möglichst über die definierten Schnittstellen (Methoden) zu erfolgen hat.


das klingt sehr nach c++.
python erlaubt das aber und in der fachliteratur (z.b python workshop v. schwarzer /s. 150-152), wird nicht davon gesprochen, dass es eine schwäche ist. es wird auch in keinster weise davon abgeraten. immerhin scheint auch er mir ein guter erfahrener programmierer zu sein, soweit ich das beurteilen kann natürlich. bücher die im addison-wesley verlag erscheinen, sind meistens nicht schlecht.

gott bewahre, interpretiere es nicht, dass ich mich frage wer von euch mehr kann, das kann und will ich auch nicht beurteilen.

schlussendlich frage ich mich einfach, warum die pythonentwickler diese möglichkeit zugelassen haben. abgesehen davon kann das wohl eh nur mit einer interpretersprache funktionieren. dennoch hätte man es unterbinden können.

das ganze oop design von python scheint nicht darauf abzuzielen gleich zu sein wie in anderen sprachen, der offene charakter zeigt sich schon dadurch, dass echte private atribute, zumindest wird das immer wieder behauptet, eigentlich nicht möglich sind. angeblich wurden ähnliche möglichkeiten, wie du sie aufgezeigt hast erst später implementiert. das habe ich aus versch. diskussionen entnommen.

ausserdem habe ich mit dogmen so meine probleme. wenn es richtig ist, dass diese möglichkeit beabsichtigt und wünschenswert war, dann will ich mir überlegen, wo und wie es einen sinn machen kann. so wie es jetzt ist, brauche ich mir nur noch überlegen, ob es ein objekt, des typ a oder b ist, weitere typen können leicht hinzugefügt werden.
ich finde den grundgedanken net schlecht.
abgehen oder verschmeissen tu ich die idee gern, wenn handfeste argumente kommen, die z.b performance o.a. betreffen.

bauchschmerzen sind mir zu wenig.:D

als nächstes werde ich mal versuchen nicht die klassen, sondern auch wie in python erlaubt die objekte zu verändern. dann kann ich nämlich das modul ganz allgemein halten und je nachdem ob ich es innerhalb meiner domain crossoverguitar oder diplomarbeit verwende die objekte unterschiedlich gestalten. ich brauche dann auch nicht die pfade zum hintergrund oder stylesheets festlegen.

so das ist mal mein gedankengang zu dem thema.

also eigentlich in einem satz: was für c++ und andere sprachen und den damit verbundenen zielsetzungen, wichtig und richtig ist, muss nicht auch für python in der form gelten.

mfg

rolgal
Benutzeravatar
Dookie
Python-Forum Veteran
Beiträge: 2010
Registriert: Freitag 11. Oktober 2002, 18:00
Wohnort: Salzburg
Kontaktdaten:

Beitragvon Dookie » Dienstag 20. April 2004, 19:46

Hi rolgal,

das Ganze ist keine Frage des Könnens, sondern eher eine Frage der Philosophie und des Programmierstiels.
Auch die Sprache in der man Programmiert, ist hier nebensächlich. OOP geht auch mit Assembler, und C++ ist IMHO eh nur eine Krücke, um mit C-ähnlichem Code den Stempel Objektorientiert aufdrücken zu können.

Es ist ja auch möglich in Python mit globalen Variablen zu arbeiten, trotzdem wird es aus gutem Grund von den Meisten Pythonkennern nicht empfohlen.

Ich halte mich da eher an die wirthsche Philosophie (Niklaus Wirth: Pascal, Modula2, Oberon, ...)

Klassen sind Beschreibungen der Eigenschaften (Attribute und Methoden) von Objekten. Instanzen sind dann die konkreten Objekte, mit denen die Anwendung arbeitet. Wie die Attribute und Methoden der Klassen implementiert sind interessiert dabei die Anwenung nicht. Wenn die Anwendung eine Representation des Objekts als String braucht, ruft sie die eingebaute Funktion str mit dem Objekt als parameter auf und erhält, wenn möglich, das gewünschte Resultat. Ob der zurückgegebene String jedesmal von den Methoden die Daten(Attribute) des Objekts in einen String überführt wird oder einfach nur ein in dem Objekt gespeicherter String zurückgegeben wird oder die Daten gleich bei einer änderung relevanter Daten oder Zustände in einem anderen Attribut zu einem String zusammengesetzt wird ist völlig egal.
Auch wenn später mal eine Klasse geändert wird, und die Objekte ihre Daten aus einer Datenbank beziehen, läuft die Anwendung ohne Probleme, solange sie nicht die vorgegebenen Schnittstellen umgeht und direkt auf Attribute zugreift.

Nehmen wir z.B. eine Klasse für Farben.

Code: Alles auswählen

class Color:
    def __init__(self, r=0, g=0, b=0):
        self._data = (r, g, b)# RGB als Integer

    def __str__(self):
        fmt = "#"+"%2x"*len(self._data)
        return fmt % self._data

    def set_red(self, value):
        if type(value) is int:
            self._data[0] = value
        else:
            self._data[0] = int(value * 255.0)

    def set_green(self, value):
        if type(value) is int:
            self._data[1] = value
        else:
            self._data[1] = int(value * 255.0)

    def set_blue(self, value):
        if type(value) is int:
            self._data[2] = value
        else:
            self._data[2] = int(value * 255.0)

    def red_as_int255(self):
        return self._data[0]

    def green_as_int255(self):
        return self._data[1]

    def blue_as_int255(self):
        return self._data[2]

    def red_as_float(self):
        return self._data[0] / 255.0

    def green_as_float(self):
        return self._data[1] / 255.0

    def blue_as_float(self):
        return self._data[2] / 255.0


Im konkreten Fall werden die Farbwerte für rgb als Integer im Bereich 0..255 (8 Bit) gespeichert. Du kannst jetzt natürlich auch auf die Liste self._data direkt zugreifen und so die Fabwerte ändern. Was aber, wenn sich später herausstellt, daß 255 Farbabstufungen doch zu wenig sind und besser 16 Bit pro Farbe verwendet werden oder gleich die Farbwerte als Floats gespeichert werden sollten. Wenn Du jetzt auf self._data direkt zugreifst, bekommst Du natürlich völlig andere Werte als Du erwartest. Und wenn du jetzt schreibend auf self._data zugreifst, bringst Du die dann auch einen anderen Wertebereich erwartende __str__ Methode durcheinander. Also musst Du überall wo du auf self._data zugreifst auf die neue interne Representation eingehende Änderungen machen.

Wenn Du jetzt z.B. auch einen Alphawert für Transparenz in der Farbe speichern willst, kannst Du natürlich eine Instanz von Color namens farbe auch so um einen Alphakanal erweitern farbe.alpha = 255 und wo du die Transparenz dann auf farbe.alpha zugreifen, aber bei der Umwandlung in einen String ist der Alphakanal verloren.

Ist es da nicht besser eine neue Klasse ColorA zu erstellen, die von Color abgeleitet ist und eben intern den zusätzlichen Wert für den Alphakanal und die Methoden um diesen zu Manipulieren zur Verfügung stellt?

Code: Alles auswählen

class ColorA(Color):
    def __init__(self, r, g, b, a):
        Color.__init__(self, r, g, b)
        self._data.append(a)

    def set_alpha(self, value):
        if type(value) == int:
            self._data[3] = value
        else:
            self._data[3] = int(value * 255.0)

    def alpha_as_int255(self):
        return self._data[3]

    def alpha_as_float(self):
        return self._data[3] / 255.0



Gruß

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

Beitragvon Leonidas » Mittwoch 21. April 2004, 16:54

Dookie hat geschrieben:in Python kannst Du Attribute mit __ anfangen lassen, dann sind sie nur über Umwege direkt zugreifbar, oder du verwendest New-style Klassen mit Properties, wenn dort nur die get-Methode definiert ist, haben diese auch nur lesezugriff.

Das erste (__) ist ja das namespace mangling, das ist ja nur einfaches umbenennen. Werden in den Neuen klassen, die namespaces immer noch als arrays ([]) gespeichert wie in den alten?
My god, it's full of CARs! | Leonidasvoice vs Modvoice
Benutzeravatar
Dookie
Python-Forum Veteran
Beiträge: 2010
Registriert: Freitag 11. Oktober 2002, 18:00
Wohnort: Salzburg
Kontaktdaten:

Beitragvon Dookie » Mittwoch 21. April 2004, 17:22

Hi Leonidas,

Wenn du in den New-style Klassen __slots__ verwendest wird kein Dictionary mit den Attributnamen und Werten angelegt. Bei Verwendung von Properties kannst Du auch "readonly" Attribute erzeugen, indem nur eine get-Methode dafür definiert wird. Das eigentliche Attribut kann dann mit namespacemangling "versteckt" werden, was IMHO völlig ausreicht, ein bisschen Verantwortung sollte auch noch dem Programmierer überlassen bleiben. Properties können auch einen eigenen Docstring bekommen, was die Dokumentation sehr erleichtert und dort kann dann auf die kritischen Sachen hingewiesen werden.


Gruß

Dookie
Gast

Beitragvon Gast » Mittwoch 21. April 2004, 20:02

hallo dookie!

Ist es da nicht besser eine neue Klasse ColorA zu erstellen, die von Color abgeleitet ist und eben intern den zusätzlichen Wert für den Alphakanal und die Methoden um diesen zu Manipulieren zur Verfügung stellt?


ich kann doch aber auch die klasse so konzipieren, dass sie grundsätzlich auf alles vobereitet ist. ich meine, ich kann mir beim entwurf überlegen, was kann eine htmlseite grundsätzlich alles beinhalten. oder was verwende ich für seiten, also mit welchen mitteln gestalte ich: z.b.

Code: Alles auswählen

<div></div>

die abstrakte klasse kann dann alle erdenklichen elemente haben, als leere ' ' oder mit einem default, und genau den ueberschreibe ich bei bedarf. abgeleitete klassen, unterscheiden sich dann in einem bestimmten merkmal. eine formularseite ist eben etwas besonderes, und eine bestaetigungsseite auch usw.
klar was ich meine? die dinge sind gar nicht so leicht zu beschreiben:D :D

ich wuerde wohl nie eine klasse farben definieren, die keinen alpha wert kennt.


Es ist ja auch möglich in Python mit globalen Variablen zu arbeiten, trotzdem wird es aus gutem Grund von den Meisten Pythonkennern nicht empfohlen.


das habe ich auch schon mehrfach gelesen. die frage ist, ob es ein guter vergleich ist. ich kenne mich zuwenig aus, um jetzt behaupten zu können, ob man beim entwurf einer sprache globale variablen unterbinden könnte. rein vom gefühl her glaube ich nicht, da es ja immer einen globalen namensraum geben muss. und wohl auch andere zuweisungen dann nicht funktionieren würden die im globalen namensraum stehen. ist jetzt aber nur so vom bauch heraus.

wie auch immer, beim klassendesign hätte man es unterbinden können, attribute und methoden von aussen her an klassen oder objekte zuzuweisen.

es geht mir um die überlegung, ob darin nicht auch reizvolle möglichkeiten liegen.
um das richtig einzuschätzen zu können, fehlt mir ganz einfach die erfahrung.

ich glaube heute halt, dass beide ansätze ihre daseinsberechtigung haben.
vielleicht falle ich auch schon bald mächtig auf die schnauze und werde brav nur noch new style klassen verwenden. :wink:

mfg

rolgal
Benutzeravatar
Dookie
Python-Forum Veteran
Beiträge: 2010
Registriert: Freitag 11. Oktober 2002, 18:00
Wohnort: Salzburg
Kontaktdaten:

Beitragvon Dookie » Mittwoch 21. April 2004, 20:46

Hi rolgal,

Python in den Früheren Versionen wurde von (OOP)Programmierern für (OOP)Programmierern, entwickelt. Du kennst ja auch sicher Programme, die von Programmierern für Programmierern geschreiben wurden, und was für "Schindluder" man damit treiben kann, bzw wie schnell gerade nicht so versierte Anwender ihr System damit schrotten können.

Daß inzwischen bei Python nachträglich einige Limitationen eingebaut wurden, hat IMHO seinen Grund darin, die Sprache für Anfänger noch tauglicher zu machen und ihnen das OOP-Konzept näher zu bringen. Dazu gehört eben auch die neuen Konzepte, die in den New-style Klassen verwirklicht wurden.

Daneben ist Python ja auch insofern flexibel, daß man nicht unbedingt objektorientiert programmieren muß, sondern (auch) funktional oder prozedural, je nach Anforderung.


Gruß

Dookie
Gast

Beitragvon Gast » Mittwoch 21. April 2004, 21:02

hi dookie!

limitationen. gut, aber man hat es daneben entstehen lassen und nicht geändert. wegen eventueller kompatibilitätsprobleme hätte man sicher keine rücksicht genommen. wenn etwas nur schlecht ist, dann muss es raus. ist ja mit anderen sachen auch passiert. ich meine jetzt nicht nur python.

funktional? prozedural?, sicher,.....

vielleicht auch oop unter anderen aspekten. also mit einem anderen zugang.

mfg

rolgal
Benutzeravatar
Dookie
Python-Forum Veteran
Beiträge: 2010
Registriert: Freitag 11. Oktober 2002, 18:00
Wohnort: Salzburg
Kontaktdaten:

Beitragvon Dookie » Mittwoch 21. April 2004, 21:17

Hi rolgal,

bei einem .x Versionssprung wird wohl nichts rausgenommen, eben wegen der Kompatibilität, sieht man ja auch daran, das bei den 2.x Versionen gegenüber den 1.x Versionen, einige Sachen rausgeflogen sind bzw als depricated eine Warnung ausgeben bei der Benutzung.

Mal schaun wie dann die 3.x Version von Python ausschaut und was dort dann für grösseren Änderungen enthalten sind.

Wenn man sich mal andere Software anschaut, da ist Python in der Version 2.3 schon sehr weit fortgeschritten. Bei Windows kam z.B. weder die 1.x noch die 2.x Version jeh auf den Markt ;)


Gruß

Dookie
Gast

Beitragvon Gast » Mittwoch 21. April 2004, 21:23

hi dookie!

ok, warten wir ab :!:

wenn bei python 3.0 diese optionen nicht draussen sind, dann muss an meiner argumentation doch irgendwas dran sein :D

oder wie würdest du das dann deuten 8)

wenn nicht, na ja dann, weiss ich auch nicht,....dann geht auf jeden fall wieder eine runde auf micht :wink:

bei windows ist es wohl ein wunder, dass überhaupt irgendwas auf den markt kam und kommen durfte, lol

vor diesem hintergrung kann ich meine klassen ruhig mit attributen und methoden von aussen bombardieren, das ist dann immer noch besser, als........ok, ich halte die klappe, sonst werden wir noch verschoben :(

mfg

rolgal
Gast

Beitragvon Gast » Donnerstag 22. April 2004, 20:19

hi zusammen!

ich finde es schade, dass zu dem thema 'klassendesign' nicht mehr leute mitdiskutieren.
es gibt abgesehen von dookie's standpunkt und meinem noch eine vielzahl anderer meinungen zu dem thema, nehme ich mal an.

immerhin, wird das thema doch recht oft aufgerufen.

mfg

rolgal
Milan
User
Beiträge: 1078
Registriert: Mittwoch 16. Oktober 2002, 20:52

Beitragvon Milan » Donnerstag 22. April 2004, 20:45

rolgal hat geschrieben:hi zusammen!

ich finde es schade, dass zu dem thema 'klassendesign' nicht mehr leute mitdiskutieren.
es gibt abgesehen von dookie's standpunkt und meinem noch eine vielzahl anderer meinungen zu dem thema, nehme ich mal an.


Hi. Tja, was soll ich sagen... Dookie ist immer schneller als ich und schreibt genau dass, was ich wenn auch schreiben will :wink: Sein Klassenmodell von "Seite" trifft numal ziemlich oft in Python auf und ist ja auch ungeheuer praktisch. Warum also nicht gleich von Anfang an auf Ausbau der Klasse setzen, wo dann nur eine Dict-Eintrag geändert werden muss. Soviel dazu, denn auch wenn deine Klassen funktionstüchtig sind, so ist bei jeder Änderung doch immer ein gewisser Mehraufwand notwendig, erst recht, wenn etwas im HTML-Text geändert werden soll (ich referenziere hier mal sowohl auf den Thread, als auch auf dein "besser so oder so", für mich hängen sie eh zusammen).

Und nun zu deiner Vorstellung von OOP: in Python ist es gangbar, von außen Klassen zu durchleuchten, aber dazu musst du wissen, wie die Klasse geschrieben ist (also den Quellcode kennen). Sonst kann 1-2-3 mal ganz schnell was dumm laufen. Hier würde ich nur auf Dookies Argument evrweisen, dass man Objekten die Möglichkeit geben sollte, auf Einflussnahme zu reagieren. Das musst du zwar nicht, aber dann solltest du dir 100% sicher sein, dass nix passiert. Das ist schlechter Stil, wenn Code nur unter gewissen Bedingungen läuft. Es könnte ja sein, dass du mal schnell eine Verbesserung in deiner Klasse machst und dann ist alles krumm und schief, da keine offizielle Schnittstelle angesprochen wird (die dann nämlich immer das gleiche nach Vereinbarung liefern muss, unabhängig davon, wie der Code intern aussieht).

Es ist einfach praktischer "echtes" OOP zu machen, da wie oben schon geschrieben bei Änderungen kein Mehraufwand dadurch entsteht, dass ich alle aufrufenden Programmteile ändern muss.

vielleicht etwas verworren, aber ich hoffe, du kannst erkennen, worauf ich hinaus will.

Milan

Wer ist online?

Mitglieder in diesem Forum: Google [Bot]