Verständnis Problem im Namensraum

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
elfrosch
User
Beiträge: 3
Registriert: Dienstag 5. Oktober 2010, 14:32

Hallo,

eigentlich wollte ich das usenet fragen, bloß spinnt mein reader gerade. Ich habe heute mein erstes Python Program, mit hilfe einer Reference geschrieben. Nun habe ich ein verständis Problem mit dem Namensraum, ich habe meine Reference so verstanden das der Globale-Namensraum inner halb einer Datei gilt. Ich habe folgenden code:

Code: Alles auswählen

def HandleCommMc(ser, cmd2Mc, logfileName):
    ser.write(cmd2Mc + _Eol)
    time.sleep(1)
    answer = ReadData(ser)
    LogMcReturn(logfileName, cmd2Mc, answer)

def GetTaskInformation(ser,config, logfileName):
    tasklist = GetListOfLines(logfileName)
    tasklist = FindTasks(tasklist, config)
    if len(tasklist) > 0:
        for i in range(len(tasklist) -1):
            task = GetTaskName(tasklist[i][0])
            if task[0] == True:
                HandleCommMc(ser, 'intrp_GetInfo("' + task[1] + '")', logfileName)
            HandleCommMc(ser, 'tt ' + tasklist[i][1], logfileName)
            HandleCommMC(ser, 'checkStack(' + tasklist[i][1] + ')',logfileName)
            HandleCommMC(ser, 'taskRegsShow(' + tasklist[i][1] + ')',logfileName)
    else:
        logfile = open(logfileName, 'a')
        try:
            logfile.write('No ' + config['misc.findtasks'] + ' tasks found' + _Eol)
        finally:
            logfile.close()
Nun behauptet mein Python (2.5) es würde HandleCommMc nicht kennen:
Traceback (most recent call last):
File "C:\Dokumente und Einstellungen\elfrosch\Desktop\McDump.py", line 259, in <module>
GetTaskInformation(ser, config, logfileName)
File "C:\Dokumente und Einstellungen\elfrosch\Desktop\McDump.py", line 221, in GetTaskInformation
HandleCommMC(ser, 'checkStack(' + tasklist[1] + ')',logfileName)
NameError: global name 'HandleCommMC' is not defined


Nach meinem Verständis befindet sich HandleCommMc im Globalen Namensraum, zu mal auch der Interpreter eine Zeile oberhalb die Routine HandleCommMC noch kennt. Erst dachte ich es würde sich um einen Tippfehler von mir handeln, ctrl+f in meinem Editor behauptet sie sind gleich geschrieben. Nun denke ich es liegt an meinem falschen Verständnis. Google konnte mir jeden falls nicht helfen.

Ich hoff ich geh mit meiner Rookie-Frage niemandem auf den Sack, aber ich blick's g'rad echt nicht.

Danke und viele Grüße

Elias
Nebelhom
User
Beiträge: 155
Registriert: Mittwoch 19. Mai 2010, 01:31

Du hast einen Tippfehler. Letztes C

Code: Alles auswählen

HandleCommMc(ser, 'tt ' + tasklist[i][1], logfileName)
HandleCommMC(ser, 'checkStack(' + tasklist[i][1] + ')',logfileName)
elfrosch
User
Beiträge: 3
Registriert: Dienstag 5. Oktober 2010, 14:32

Fail Hard! mein Editor ist bei der Suche nicht case sensitive, wie peinlich.

Danke und Srry

Elias
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Hallo.

Noch ein paar Hinweise zu deinem Code:
- Das "> 0" und "== True" kannst du einsparen
- Man kann direkt über Listen iterieren und braucht dazu nicht die range-Funktion und diese ganze Indizes
- Strings solltest du nicht mit "+" zusammensetzen, dafür gibt es andere Mechanismen (such mal nach "String Formatting")
- "tasklist" ist ein schlechter Name. Wenn du den Typ änderst, müsstest du überall den Namen anpassen. Verwende besser "tasks".

Sebastian
Das Leben ist wie ein Tennisball.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Noch mehr Anmerkungen:

- Beachte PEP8
- Dateien öffnet man am besten mit "with"; damit wird eine Datei immer geschlossen, unabhängig von Exceptions.
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
elfrosch
User
Beiträge: 3
Registriert: Dienstag 5. Oktober 2010, 14:32

Hallo Sebastian hallo Hyperion,

danke für die hinweise. Ich will sowieso noch refactorieren. Mir fehlt es noch ein weinig an gefühl für die Sprache, ich denke jedoch es kommt schnell, da Python sich vom ersten Eindruck sehr geschmeidig anfühlt.

Gruß Elias
BlackJack

@elfrosch: Noch ein wenig "Manöverkritik" zum Quelltext an sich:

In Python kann man direkt über Elemente einer Liste beziehungsweise Datentypen die "iterable" sind, iterieren ohne einen Index als Umweg benutzen zu müssen. So etwas wie ``range(len(obj))`` ist in den allermeisten Fällen unnötig. Falls man doch einmal den Index zusätzlich zum jeweiligen Element benötigt, gibt es die `enumerate()`-Funktion.

An der Stelle frage ich mich übrigens ob es Absicht ist, dass Du das letzte Element von `tasklist` *nicht* berücksichtigst? Falls das Absicht sein sollte, würde ich das anders ausdrücken. Entweder über ein "slice" von der Liste ohne das letzte Element iterieren, oder falls es generell nicht benötigt wird, es vorher aus der Liste entfernen.

Neben den Indexzugriffen in Schleifen sind Indexzugriffe in Listen oder Tupel mit Konstanten nicht besonders aussagekräftig und verständlich. Zum Beispiel muss man wissen oder was 0 und 1 bei den jeweiligen `tasklist`-Einträgen bedeuten. Wenn man die Elemente an aussagekräftige Namen binden würde, brächte man sich da nicht so viele Gedanken darüber machen.

Man sollte versuchen Wiederholungen im Quelltext zu Vermeiden und Unterschiede als Daten aus sich wiederholendem Quelltext zu ziehen und Funktionen oder Schleifen mit diesen Daten zu verwenden. Die drei Aufrufe von `HandleCommMC()` unterscheiden sich zum Beispiel eigentlich nur im zweiten Argument.

`GetTaskInformation()` könnte zum Beispiel so aussehen (ungetestet):

Code: Alles auswählen

def GetTaskInformation(ser, config, logfileName):
    tasks = FindTasks(GetListOfLines(logfileName), config)
    if tasks:
        tasks.pop()     # TODO Document *why* the last entry is ignored.
        for tasks_i_0, tasks_i_1 in tasks:
            task_0, task_1 = GetTaskName(tasks_i_0)
            if task_0:
                HandleCommMc(ser, 'intrp_GetInfo("%s")' % task_1, logfileName)
            for command in ['tt %s', 'checkStack(%s)', 'taskRegsShow(%s)']:
                HandleCommMC(ser, command % tasks_i_1, logfileName)
    else:
        with open(logfileName, 'a') as logfile:
            logfile.write('No %s tasks found%s'
                          % (config['misc.findtasks'], _Eol))
Natürlich mit `tasks_i_0`, `tasks_i_1`, `task_0`, und `task_1` durch Namen ersetzt, die aussagekräftiger sind und dem Leser einen Hinweis darauf geben was die Bedeutung der Objekte hinter diesen Namen ist.

Eventuell könnte das Programm auch von objektorientierter Programmierung profitieren.
Antworten