Was ist das Objekt?

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
Benutzeravatar
Kuttengeier
User
Beiträge: 27
Registriert: Freitag 17. August 2007, 07:04

Mittwoch 22. August 2007, 08:11

Hallo,

ich möchte jetzt meinen Notizblock objektorientiert gestalten.

Ich kann mich leider nicht entscheiden, welches das Objekt ist, dass ich programmiere. Ist es der Block, der als Methoden "anzeigen" (...der Einträge), "löschen" (...der Einträge) und "hinzufügen" (...der Einträge) hat, oder nehme ich als Objekt lieber die Notizen? Oder vielleicht sogar beides? Bei den Notzien hätte ich mir das jetzt so vorgestellt: "eintragen", "auslesen" und "löschen".

Macht es vielleicht sogar Sinn, dass man die beiden Objekte so miteinander verknüpft, dass man mit dem Notizobjekt eine Notiz erstellt und mit dem Blockobject aufnehmen muss? Ich stell mir das so vor:

Notiz -> request an das Objekt "Block": erstellen("blablabla...")
Block -> Muss request annehmen und erst dann wird eingetragen


Also, um mein Problem nochmal kurz zu beschreiben: Ich kann mich nicht entscheiden, welches Objekt ist Programmiere. "Block", "Notiz" oder beides? Alles sind Objekte, die man schreiben könnte.

freue mich auf Antwort,
Kuttengeier
BlackJack

Mittwoch 22. August 2007, 09:01

Das kommt ganz darauf an was eine Notiz und ein Block ist/können muss. Mach Dir am besten mal klar welche Datenattribute und welche Methoden und generell welches Verhalten beide haben müssen.
Leonidas
Administrator
Beiträge: 16024
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Mittwoch 22. August 2007, 09:02

Dann schreib sie doch beide, ist doch eine gute Idee.

Du hast ein Blockobjekt, zu dem mehrere Notizobjekte gehören, die ihre Daten enthalten. Passt doch wunderbar.

Was du machen kannst, wäre es, das Blockobjekt von der Liste erben zu lassen und an deine Bedürfnisse anassen. Dann bekommst du nämlich ``extend()``, ``append()``, ``pop()`` usw. gratis dazu.
My god, it's full of CARs! | Leonidasvoice vs Modvoice
Benutzeravatar
Kuttengeier
User
Beiträge: 27
Registriert: Freitag 17. August 2007, 07:04

Mittwoch 22. August 2007, 09:21

OK,

aber dass mit dem Erben lass ich erstmal bleiben, weil mir das bis jetzt ein bisschen kompliziert ist. Hab zwar schon gelesen, wie das geht, aber zutrauen tu ich mir das noch nicht.

Ich mach es erstmal so mit der Liste. Das muss ich mir auch nochmal durch den Kopf gehen lassen, wie ich das sinvoll hinbekomme. Aber da aber schon ein paar Ideen. Wenn ich damit fertig bin schreibe ich euch den Source und erwarte natürlich, dass ich Verbesserungsvorschläge bekomme ;)

in diesem Sinne,
Kuttengeier
Benutzeravatar
Kuttengeier
User
Beiträge: 27
Registriert: Freitag 17. August 2007, 07:04

Donnerstag 23. August 2007, 05:54

So,

Ich habe mich jetzt zwei Tage drangesetzt und dabei einiges fabriziert.

Kommentare stehen dran und sollten des QT erklären. Bisher gibt es noch keine "löschen"-Funktion und die ID muss auch von Hand eingegeben werden und es existiert noch keine Überprüfung, ob eine ID nicht zweimal existiert.

Aber ich glaube, dafür, dass es mein erstes sinnvolles OOP Skript ist is es nicht schlecht :)

Naja, schauts euch an, und ich will natürlich auch Feedback lesen!

Code: Alles auswählen

#!/usr/bin/python

from __future__ import with_statement
import pickle
import sys

#config
notice_file = "save.bin"
bedingung = True
#/config

#Die "Notizzettel ohne Methoden"
class notice:
    id=''
    title=''
    content=''
   
class blog:
    notices = []
    #Konstrucktor, sorgt dafuer, dass die Notizen aus dem file geholt werden
    def __init__(self):
        try:
            with open(notice_file, "rb") as fs:
                blog.notices = pickle.load(fs)
        except:
            print "Fehler"
    #Notizen hinzufuegen
    def add(self, id, title, content):
        note = notice()
        note.id = id
        note.title = title
        note.content = content
        blog.notices.append(note)
        #Notizen ins notice_file eintragen
        with open(notice_file, "wb") as fs:
            pickle.dump(blog.notices, fs, 2)
    #Notizen loeschen
    def delete(self, id):
        if id == 'all' or id == 'All':
            blog.notices = []
            with open(notice_file, "wb") as fs:
                pickle.dump(blog.notices, fs, 2)
        else:
            for i in range(len(blog.notices)):
                #suchen in allen id-Feldern des Blogs nach uebergebener id. Wenn gefunden die ausgeben
                if id == blog.notices[i].id:
                    blog.notices.pop(i)
                    with open(notice_file, "wb") as fs:
                        pickle.dump(blog.notices, fs, 2)
                    break
       
    #Anzeigen der Noitzen.
    def show(self, id=0):
        #Wenn keine id uebergeben wird werden alle eintraege angezeigt
        if id == 0:
            for i in range(len(blog.notices)):
                print str(blog.notices[i].id)+'|'+blog.notices[i].title
        else:
            #ansonsten wird die Notiz eingezeit, die per id uebergeben wurde.
            for i in range(len(blog.notices)):
                #suchen in allen id-Feldern des Blogs nach uebergebener id. Wenn gefunden die ausgeben
                if id == blog.notices[i].id:
                    print blog.notices[i].content
                    break

b = blog()
#Die Eingabeaufforderung, ueberpruefen der Benutzerbefehle
while bedingung:
    #Speichern des Befehles
    input = raw_input(">>")
    #Auswerten der Befehle
    if input == 'help' or input == 'Help':
        print "Dies ist die Hilfe"
    if input == 'input' or input == 'Input':
        id = raw_input('ID: ')
        title = raw_input('Title: ')
        content = raw_input('Content: ')
        if id != '' and title != '' and content != '':
            b.add(id, title, content)
    if input == 'show' or input == 'Show':
        id = raw_input('ID: ')
        b.show(id)
    if input == 'showall' or input == 'Showall':
        b.show()
    if input == 'delete' or input == 'Delete':
        id = raw_input('ID: ')
        b.delete(id)
    if input == 'exit' or input == 'Exit':
        sys.exit()
.:edit:.
Habe noch eine Löschenfunktion mit eingebaut. Nicht elegant, aber selten
Leonidas
Administrator
Beiträge: 16024
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Donnerstag 23. August 2007, 08:58

Naja, dann fange ich mal an: du könntest dem Skript noch eine Encoding-Zeile angeben, das schadet nicht und ist meist sogar hilfreich, wenn man mit Unicode arbeitet.

Dann: Klassennamen schreibt man groß, damit man sie von Funktionsnamen unterscheiden kann. Welchen Sinn die IDs haben, erschließt sich mir nicht, denn um zwei Notizen zu vergleichen kann man auch ``__cmp_``, ``__eq__`` und Co implementieren. Variablen werden in der Regel in ``__init__`` initialisiert und nicht im Klassenkörper, außer du planst sie als Klassenvariablen zu nutzen.

Achja, es gibt so etwas wie Docstrings, da musst du die Kommentare nicht oben über die Funktionen und Klassen schreiben und man kann mit``help()`` (und ``?``) auf diese zugreifen.

Man sollte nie generell alle Exceptions fangen, sondern immer nur spezifische um sicherzugehen, dass die Fehlerbehandlung auch das macht was sie machen soll. Die Ausgabe "Fehler" ist für den User schlichtweg unbrauchbar.

Statt die pickle-Datei in jederFunktion zu schrieben, würde ich das in eine Extra-Funktion auslagern,damit sich der Code nicht ständig wiederholt. Statt ``show()`` könntest du ``__repr__()`` nutzen, dann kann das Objekt auch im Python-Interpreter schön angezeigt werden. Wenn du ``add()`` in ``append()`` und ``delete()`` in ``pop()`` umbenennen würdest, dann hättest du zumindest ein Listenähnliches API.

Dann solltest du auf jeden Fall den Code unten in eine Funktion packen und diese erst mach der Prüfung von ``__name__`` aufrufen - sonst wird der Code auch aufgerufen, wenn das Modul importiert wird und das will man in der Regel nicht.
My god, it's full of CARs! | Leonidasvoice vs Modvoice
BlackJack

Donnerstag 23. August 2007, 09:28

Das geht einiges schief. Die Klasse wird im Programmverlauf durch eine gleichnamige Instanz ersetzt und der Klassen-Code greift dann immer auf dieses eine Objekt direkt zurück. Benenn mal die Klasse in `Blog` um und die Instanz in irgend etwas anderes und schon funktioniert's nicht mehr. So auf den ersten Blick wird nicht einmal `self` verwendet!

Du machst immer Schleifen über Indexe statt über die Listen selbst. Das ist in 99% der Fälle überflüssig und zu kompliziert. Man kann direkt über Elemente von Listen iterieren. Die erste Schleife in `show()` würde man so schreiben:

Code: Alles auswählen

        for note in self.notices:
            print '%d|%s' % (note.id, note.title)
Benutzeravatar
Kuttengeier
User
Beiträge: 27
Registriert: Freitag 17. August 2007, 07:04

Donnerstag 23. August 2007, 11:39

Erstmal vielen dank für die Tipps.

Ich habe vieles schon durchprobiert und ziemlich überrascht, dass es so einfach kalppt. Leider wusste ich nichts von dem was ihr mir geschrieben habt. Muss ich mir also erst alles neu aneignen. Das man nach Objekten in einer Liste einfach so suchen kann war mir völlig neu. War überrascht, dass es geklappt hat :)

Naja, danke und werde die "Fehler" mal anfangen zu berichtigen. Wenn ich fertig bin melde ich mich nochmal und poste gegebenfalls nochmal den Code.

Also, indesem Sinne,
Kuttengeier

.:edit:.
Habe da nochmal eine Frage zu der For Schleife, die BlackJack da geschrieben hat: Wie sucht das Programm in der Liste? Nach dem note-"Muster", also dem Aufbau von note, oder nach den Werten, die Note enthält?
Antworten