Invalid Syntax an komischer Stelle | Telefonbuchklasse

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.
CrackPod
User
Beiträge: 205
Registriert: Freitag 30. Juni 2006, 12:56

Invalid Syntax an komischer Stelle | Telefonbuchklasse

Beitragvon CrackPod » Sonntag 2. Juli 2006, 00:09

Hallo,

da ich mir aus Testzwecken ein Kommandozeilentelefonbuchprogramm progammieren will, hab ich mal eine Klasse entworfen(noch nich wirklich weit)
Jedoch bekomm ich eine Fehlermeldung:
$ python telefonbuch.py
File "telefonbuch.py", line 36
Mobil:\t %s' % (self.name, self.nName self.vName, self.strasse, self.plz, self.ort, self.privat, self.mobil)
^
SyntaxError: invalid syntax

Mein Code sieht folgendermaßen aus:

Code: Alles auswählen

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

class Eintrag:
    '''Diese Klasse erstellt Einträge für das Telefonbuch'''
    eintraege = 0
   
    def __init__ (self, nName = '', vName = '', strasse = '', plz = '', ort = '', privat = '', mobil = ''):
        if len(name) > 1:
            self.nName      = nName
        if len(vName) > 1:
            self.vName      = vName
        if len(strasse) > 1:
            self.strasse    = strasse
        if len(plz) > 1:
            self.plz        = plz
        if len(ort) > 1:
            self.ort        = ort
        if len(zuhause) > 1:
            self.privat     = privat
        if len(mobil) > 1:
            self.mobil      = mobil
        if len(self.name) > 1 and len(self.vName) > 1:
            self.name       = self.nName+','+self.vName

        Eintrag.eintraege += 1

    def __str__ (self):
        output = '###### Eintrag für: %s ###### \
                Name:\t %s \
                Vorname:\t %s \
                Straße:\t %s \
                Postleitzahl:\t %s \
                Ort:\t %s \
                Privat:\t %s \
                Mobil:\t %s' % (self.name, self.nName self.vName, self.strasse, self.plz, self.ort, self.privat, self.mobil)
        return output

einer = Eintrag('xy', '', 'irgendwo', 'der', 'ort', '2134444', '11654')
print einer

Kann mir einer sagen, warum der Fehler kommt und wie ich ihn beheben kann?
Wenn ich im falschen Bereich gelandet bin, dann tut mir das Leid, aber ich wusst jetz nich so genau, wohin damit...

Greetz
Zuletzt geändert von CrackPod am Sonntag 2. Juli 2006, 10:11, insgesamt 1-mal geändert.
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5554
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Telfs (Tirol)
Kontaktdaten:

Re: Invalid Syntax an komischer Stelle

Beitragvon gerold » Sonntag 2. Juli 2006, 00:59

CrackPod hat geschrieben:Jedoch bekomm ich eine Fehlermeldung: [...] SyntaxError: invalid syntax
[...]
Kann mir einer sagen, warum der Fehler kommt und wie ich ihn beheben kann?

Hi CrackPod!

InvalidSyntax --> Du hast etwas so geschrieben, dass der Interpreter nicht daraus schlau wird. Du hattest einen Beistrich zwischen self.nName und self.vName vergessen. (Zeile 37)

Allerdings gibt es noch ein paar Ungereimtheiten. Die Klasse "Eintrag" stellt nur **einen** Eintrag des Telefonbuchs dar. Damit hat die Klassenvariable "eintraege" eigentlich nichts in diesem Eintrag zu suchen. Eine Zählung der Einträge sollte in der noch nicht existierenden Klasse "Telefonbuch" stattfinden. Dort kannst du deine Einträge sammeln und auch Buch über die Menge führen.

Der Code

Code: Alles auswählen

Eintrag.eintraege += 1
verändert nur die Klassenvariable. ---> Die nächste, neu erstellte, Klasseninstanz hat damit als Basis der Zählung einen korrekten Wert. Was passiert allerdings, wenn du eine Adresse löscht? So wird die Zählung nicht funktionieren. Lösung siehe vorherigen Absatz --> Klasse: Telefonbuch.

Wenn du in der Klasse Telefonbuch alle Einträge verwaltest, dann brauchst du nicht mehr über die Menge der Einträge Buch zu führen. Warum? Weil du dort wahrscheinlich deine Einträge in einer Liste oder in einem Dictionary verwalten wirst. Wenn ja, dann kannst du ja mit len() die Größe der Liste abfragen.

Dann habe ich noch etwas: Es bringt dir keinen Vorteil, wenn du die beim Initialisieren der Klasse NICHT übergebenen Variablen nicht in die Klasseninstanz schreibst.

Code: Alles auswählen

def __init__(self, vorname = "", nachname = "", ...):
    self.vorname = vorname
    self.nachname = nachname

So kannst du immer auf die Instanzvariablen self.vorname und self.nachname zugreifen. -- Ohne dass es einen Fehler gibt, wenn diese nicht existieren.

self.name -- das ist so eine fix codierte Sache, die dir Probleme machen wird, wenn sich bei irgendjemand der Nachname ändert. Und das ist bei einer Hochzeit ziemlich oft der Fall. Oder, was ist, wenn ich beim Eintragen den Vornamen noch nicht weiß. Diesen also erst später nachtrage? Besser wäre es, wenn du auf die Variable "self.name" verzichten würdest und diese immer neu zusammensetzt, wenn sie gebraucht wird.

Das kannst du ständig beim Gebrauch machen, oder du erstellst dir dafür eine Methode und evt. sogar ein Property.

Code: Alles auswählen

class Eintrag(object):
   
    ...
    ...
   
    def get_name(self):
        """
        Gibt den Namen, bestehend aus Vorname und Nachname zurück
        """
       
        return self.vorname + "," + self.nachname


    def __str__ (self):
        output = (
            "###### Eintrag fuer: %s ###### \n"
            "Name:\t %s \n"
            "Vorname:\t %s \n"
            "Strasse:\t %s \n"
            "Postleitzahl:\t %s \n"
            "Ort:\t %s \n"
            "Privat:\t %s \n"
            "Mobil:\t %s"
        ) % (
            self.get_name(), self.nName, self.vName, self.strasse,
            self.plz, self.ort, self.privat, self.mobil
        )
        return output

Dein Ansatz ist schon mal nicht schlecht. Jetzt musst du nur noch an den Feinheiten arbeiten.

mfg
Gerold
:-)

Edit: Klammern vergessen ;-)
Zuletzt geändert von gerold am Sonntag 2. Juli 2006, 01:16, insgesamt 2-mal geändert.
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
CrackPod
User
Beiträge: 205
Registriert: Freitag 30. Juni 2006, 12:56

Beitragvon CrackPod » Sonntag 2. Juli 2006, 01:13

Ok, hab das jetz geändert:

Code: Alles auswählen

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

class Eintrag:
    '''Diese Klasse erstellt Einträge für das Telefonbuch'''
   
    def __init__ (self, nName = '', vName = '', strasse = '', plz = '', ort = '', privat = '', mobil = ''):
        self.nName      = nName
        self.vName      = vName
        self.strasse    = strasse
        self.plz        = plz
        self.ort        = ort
        self.privat     = privat
        self.mobil      = mobil

        Eintrag.eintraege += 1

    def getName(self):
        if len(self.nName) > 1 and len(self.vName) > 1:
            return self.nName + ',' + self.vName
        elif len(self.nName > 1):
            return self.nName
        else:
            return self.vName

    def __str__ (self):
        output = '###### Eintrag für: %s ###### \n\
                Name: %s \n\
                Vorname: %s \n\
                Straße: %s \n\
                Postleitzahl: %s \n\
                Ort: %s \n\
                Privat: %s \n\
                Mobil: %s\n' % (self.getName, self.nName, self.vName, self.strasse, self.plz, self.ort, self.privat, self.mobil)
        return output

einer = Eintrag('xy', '', 'irgendwo', 'der', 'ort', '2134444', '11654')
print einer

Meine Ausgabe sieht jedoch teilweise komisch aus :D irgendwas stimmt mit der Funktion nicht:
###### Eintrag für: <bound method Eintrag.getName of <__main__.Eintrag instance at 0xb7ddde8c>> ######
Name: xy
Vorname:
Straße: irgendwo
Postleitzahl: der
Ort: ort
Privat: 2134444
Mobil: 11654

Was is falsch?
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5554
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Telfs (Tirol)
Kontaktdaten:

Beitragvon gerold » Sonntag 2. Juli 2006, 01:19

CrackPod hat geschrieben:Was is falsch?

Hi CrackPod!

Das ging aber schnell. :-)

Ich habe in meinem Beispiel die Klammern vergessen:

Code: Alles auswählen

...self.get_name(), self.nName, self.vName, self.strasse,

mfg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs

Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
CrackPod
User
Beiträge: 205
Registriert: Freitag 30. Juni 2006, 12:56

Beitragvon CrackPod » Sonntag 2. Juli 2006, 01:36

Hab die Klammern angefügt. Wenn ich jedoch folgendes mache:

Code: Alles auswählen

jemand = Eintrag('name', 'vorname', 'str', 'plz', 'ort', 'privat', 'mobil')
einer = Eintrag('xy', '', 'irgendwo', 'der', 'ort', '2134444', '11654')
print jemand
print einer

Bekomm ich einen Fehler:
$ python telefonbuch.py
###### Eintrag für: name,vorname ######
Name: name
Vorname: vorname
Straße: str
Postleitzahl: plz
Ort: ort
Privat: privat
Mobil: mobil

Traceback (most recent call last):
File "telefonbuch.py", line 54, in ?
print einer
File "telefonbuch.py", line 25, in __str__
output = '###### Eintrag für: %s ###### \n\
File "telefonbuch.py", line 19, in getName
elif len(self.nName > 1):
TypeError: len() of unsized object

Was heist das? self.nName ist doch egtl instanziiert worden oder?
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5554
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Telfs (Tirol)
Kontaktdaten:

Beitragvon gerold » Sonntag 2. Juli 2006, 09:34

CrackPod hat geschrieben:Bekomm ich einen Fehler:
elif len(self.nName > 1):
TypeError: len() of unsized object

Hi CrackPod!

Da liegt nur eine falsch gesetzte Klammerung vor.

Ändere die Zeile nach

Code: Alles auswählen

elif len(self.nName) > 1:
Dann sollte es gehen.

mfg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs

Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
CrackPod
User
Beiträge: 205
Registriert: Freitag 30. Juni 2006, 12:56

Beitragvon CrackPod » Sonntag 2. Juli 2006, 10:11

Mein Gott :oops: das is mir jetz peinlich :D
Naja liegt am Python anfänger^^ Andere Syntax schnellere Fehler.(Bin die Klammersetzung if(bedingung){bla} von Java udn PHP gewohnt:D)

Ich hab die Klasse jetz mal geändert:

Code: Alles auswählen

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

class Eintrag:
    '''Diese Klasse erstellt Einträge für das Telefonbuch'''
   
    def __init__ (self, nName = '', vName = '', strasse = '', plz = '', ort = '', privat = '', mobil = ''):
        self.nName      = nName
        self.vName      = vName
        self.strasse    = strasse
        self.plz        = plz
        self.ort        = ort
        self.privat     = privat
        self.mobil      = mobil
        self.data       = [self.nName, self.vName, self.strasse, self.plz, self.ort, self.privat, self.mobil]

    def getData (self):
        output = '###### Eintrag für: %s ###### \n\
    Name: %s \n\
    Vorname: %s \n\
    Straße: %s \n\
    Postleitzahl: %s \n\
    Ort: %s \n\
    Privat: %s \n\
    Mobil: %s\n' % (self.getName(), self.nName, self.vName, self.strasse, self.plz, self.ort, self.privat, self.mobil)

        return output

    def getName (self):
        '''Erstellt einen Namen für den Telefonbucheintrag'''

        if len(self.nName) > 1 and len(self.vName) > 1:
            return self.nName + ',' + self.vName
        elif len(self.nName) > 1:
            return self.nName
        else:
            return self.vName

    def getEntry (self):
        return self.data

class Telefonbuch:
    '''Diese Klasse verwaltet die Einträge des Telefonbuchs'''

    eintraege = 0

    def __init__ (self):
        '''Initialiesierung des Dictionaries, in dem alle Adressen gespeichert werden'''

        self.adressen = {}

    def addEntry (self, nName = '', vName = '', strasse = '', plz = '', ort = '', privat = '', mobil = ''):
        '''Fügt dem Telefonbuch einen Eintrag an'''

        newAdress = Eintrag(nName = '', vName = '', strasse = '', plz = '', ort = '', privat = '', mobil = '')

        self.adressen[nName] = newAdress.getEntry
        self.adressen[vName] = newAdress.getEntry

        Telefonbuch.eintraege += 1

    def getEntry(self, name):
        '''Versucht einen Eintrag aus dem Telefonbuch zu holen'''

        if self.adressen.has_key(name):
            return self.adressen[name].getData
        else:
            return 'Kein Eintrag unter diesem Namen gespeichert.'

telBuch = Telefonbuch()
telBuch.addEntry('name', 'vorname', 'str', 'plz', 'ort', 'privat', 'mobil')
telBuch.addEntry('xy', '', 'irgendwo', 'der', 'ort', '2134444', '11654')
print telBuch.getEntry('vorname')
print telBuch.getEntry('xy')
print telBuch.getEntry('name')

Meine Ausgabe:
$ python telefonbuch.py
Traceback (most recent call last):
File "telefonbuch.py", line 80, in ?
print telBuch.getEntry('vorname')
File "telefonbuch.py", line 66, in getEntry
return self.adressen[name].getData
AttributeError: 'function' object has no attribute 'getData'

Aber eigentlich müsste das doch funktionieren oder? Ich hab doch in das Dictionary die Instanz von Eintrag gelegt?!
Oder kann ich Eintrag nich aus Telefonbuch instanziieren?
EDIT:
Oh man, ich habs *kopfklatsch*
Lauter banale Fehler:

Code: Alles auswählen

return self.adressen[name].getData #Klammernpaar hat gefehlt
self.adressen[nName] = newAdress.getEntry #1. Klammern haben gefehlt. 2. getEntry ist sinnlos! Ich brauch die Instanz nich die Daten^^
newAdress = Eintrag(nName = '', vName = '', strasse = '', plz = '', ort = '', privat = '', mobil = '') #ich hab die Parameter faulheitshalber aus dem __init__ von Eintrag kopiert und vergessen Variablen draus zu machen :D

Ich glaub, das waren soziemlich alle Fehler, die ich gemacht hab
Benutzeravatar
newone_XXV.
User
Beiträge: 50
Registriert: Dienstag 20. Juni 2006, 15:03
Wohnort: Direkt vor meinem PC
Kontaktdaten:

Beitragvon newone_XXV. » Sonntag 2. Juli 2006, 12:18

Gut wenn Du´s schon hast.... Ansonsten bin ich gerade dabei gewesen, dass ganze mal ein bisschen schöner zu machen.... :wink:
CrackPod
User
Beiträge: 205
Registriert: Freitag 30. Juni 2006, 12:56

Beitragvon CrackPod » Sonntag 2. Juli 2006, 13:05

Bevor ihr meinen Code verschönet, lasst ihn mich bitte fertigstellen. Dann hab ich das verstanden usw (bin mit der Syntax und den Feinheiten von Python vertraut). Danach könnt ihr alles so ändern, wie ihr wollt und ich schau, dass ichs versteh :D
Hab aber mittlerweile ein neues Problem:

Code: Alles auswählen

if len(sys.argv) < 2:
    sys.argv[1] = '--help'

if sys.argv[1].startswith('--'):
    args = sys.argv[1][2:]
    if args == 'help':
        print 'Se haben die Hile gestartet.'
        print 'Mögliche Parameter: add, show, showall'
        print 'Parameter `add` fügt einen Eintrag in das Telefonbuch ein.'
        print 'Parameter `show` sucht und zeigt einen Eintrag aus dem Telefonbuch.'
        print 'Parameter `showall` zeigt alle Einträge des Telefonbuches.'

Damit will ich bewirken, dass, wenn jemand das Programm nur mit

Code: Alles auswählen

$ python telefonbuch.py
starten will die Hilfe angezeigt bekommt, da man Parameter beim Start übergeben muss.
Jedoch bekomm ich folgende Terminal ausgabe:
$ python telefonbuch.py
Traceback (most recent call last):
File "telefonbuch.py", line 77, in ?
sys.argv[1] = '--help'
IndexError: list assignment index out of range
$ python telefonbuch.py --help
Se haben die Hile gestartet.
Mögliche Parameter: add, show, showall
Parameter `add` fügt einen Eintrag in das Telefonbuch ein.
Parameter `show` sucht und zeigt einen Eintrag aus dem Telefonbuch.
Parameter `showall` zeigt alle Einträge des Telefonbuches.

Also stimmt irgendwas beim ersten If nich...
Benutzeravatar
DatenMetzgerX
User
Beiträge: 398
Registriert: Freitag 28. April 2006, 06:28
Wohnort: Zürich Seebach (CH)

Beitragvon DatenMetzgerX » Sonntag 2. Juli 2006, 13:59

Code: Alles auswählen

if len(sys.argv) > 2:  #Anderst rum ;)
    sys.argv[1] = '--help'
BlackJack

Beitragvon BlackJack » Sonntag 2. Juli 2006, 14:06

Du hast im ``if`` gerade geprüft ob die Liste `sys.argv` weniger als zwei, d.h. einen Eintrag hat. Der hat den Index 0. Einen zweiten Eintrag an Index 1 gibt's nicht, also kannst Du dem auch nichts zuweisen. Du kannst aber etwas an die Liste anhängen.

Code: Alles auswählen

In [5]: a = ['blah']

In [6]: a[0] = 'blubb'

In [7]: a
Out[7]: ['blubb']

In [8]: a[1] = 'hallo'
---------------------------------------------------------------------------
exceptions.IndexError         Traceback (most recent call last)

/home/marc/<ipython console>

IndexError: list assignment index out of range

In [9]: a.append('hallo')

In [10]: a
Out[10]: ['blubb', 'hallo']
CrackPod
User
Beiträge: 205
Registriert: Freitag 30. Juni 2006, 12:56

Beitragvon CrackPod » Sonntag 2. Juli 2006, 14:27

Achso ja^^ append :oops:
Wenn was mit [] is, dann sin das - in PHP - array und da kann man einfach so was anfügen. Hatt grad ne Sprachenverknüpfung :D
Danke
CrackPod
User
Beiträge: 205
Registriert: Freitag 30. Juni 2006, 12:56

Beitragvon CrackPod » Sonntag 2. Juli 2006, 19:41

Also neuer Statusbericht:
Ich will ja mit meinem Programm Kontakte speichern, löschen, alle anzeigen, einzelne anzeigen und alle löschen können.
Nur einen Kontakt anzeigen hat wunderwar funktioniert(eintragen logischerweise aus :wink:)
Alles löschen ging auch.
Aber was nicht ging, war alle anzeigen, die sin alle doppelt gekommen, weil ich jeweils den vor und den nachnahmen in eine variable gespeichert hab, damit man nach beiden suchen kann.
Jetz hab ich das umgeschrieben. Ich hab 2 Dictionaries:
Eines, in dem als key die vor und nachnamen stehen. Als wert haben sie eine id. Und das 2. Dict enthält als key die id und als wert eine referenz auf eine Eintragen instanz.
Nur irgendwie wird wenn cih einen 2. Kontakt einfüge der 1. überschrieben.
Schaut es euch einfach ma selber an:(hab nen nopaste dienst genommen, damit man nich so ewig rumscrollen muss)
http://nopaste.info/index.php?id=7e87f16508

Hoffe mir kann einer helfen
Greetz
BlackJack

Beitragvon BlackJack » Sonntag 2. Juli 2006, 23:11

Das kann so nicht klappen. Stell Dir vor Du möchtest die Brüder Hans und Klaus Meier speichern. Vereinfachen wir den Eintrag mal nur auf Vor- und Nachname und packen sie in Tupel. Was Du machst ist jeweils Vor- und Nachname als Schlüssel auf den kompletten Namen in `adressen` abzuspeichern:

Code: Alles auswählen

In [46]: adressen = dict()

In [47]: a = ('Hans', 'Meier')

In [48]: adressen['Hans'] = a

In [49]: adressen['Meier'] = a

In [50]: adressen
Out[50]: {'Hans': ('Hans', 'Meier'), 'Meier': ('Hans', 'Meier')}


Soweit so gut, aber nun:

Code: Alles auswählen

In [51]: a = ('Klaus', 'Meier')

In [52]: adressen['Klaus'] = a

In [53]: adressen['Meier'] = a

In [54]: adressen
Out[54]:
{'Hans': ('Hans', 'Meier'),
 'Klaus': ('Klaus', 'Meier'),
 'Meier': ('Klaus', 'Meier')}


Tja, jetzt hat der Klaus Meier den Eintrag von Hans Meier beim Nachnamen überschrieben. Das gleiche Problem tritt auf, wenn Du mehrere Leute mit gleichem Vornamen speicherst.

Wenn Du die Namen in einem Dictionary speichern möchtest, dann musst Du dafür sorgen, dass der Schlüssel eindeutig ist. Beim privaten Telefonbuch kommen die meisten Leute noch damit aus, wenn man einfach den kompletten Namen nimmt, aber es soll auch Leute geben die zwei Hans Meier kennen. Dann klappt auch das nicht mehr.

Ich würde die Namen einfach in einer Liste speichern. Beim persönlichen Telefonbuch ist selbst bei mehreren hundert Einträgen linearer Zugriff bzw. lineare Suche von der Laufzeit her noch vertretbar.
CrackPod
User
Beiträge: 205
Registriert: Freitag 30. Juni 2006, 12:56

Beitragvon CrackPod » Montag 3. Juli 2006, 06:24

naja das mit der Liste hab ich mir auch schon überlegt, aber das is auch schwierig, weil zu den namen ja egtl dann noch die instanz gespeichert werden müsste.
Naja ich könnte ja ein Dictionary folgenermaßen erstellen:

Code: Alles auswählen

a = dict()
neuerEintrag()
a['Hans,Meier'] = index
neuerEintrag()
a['Klaus,Meier'] = index

Wenn dann die Namen gesucht werden, kann ich die keys splitten und durchsuchen. Wenn alle ausgegeben werden sollen geht die lineare suche auch recht gschmeidig, weil ich mir egtl ne Kopie von den Werten der Namen machen könnte und die linear aufrufen kann.
Soweit zur Theorie :D
Geht das so? Oder hab ich wieder nen Logikfehler drin?

Wer ist online?

Mitglieder in diesem Forum: Bing [Bot]