global variable in for Schleife

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.
m6T
User
Beiträge: 3
Registriert: Dienstag 20. Oktober 2009, 11:46

Hallo ;)

Also, ich versuche einige Werte, die über eine for schleife aus einer Datenbank ausgelesen werden und versch. Variablen zugewiesen werden, global verfügbar zu machen.

Das ist nötig da ich diese Variablen dann mit andren Programmteilen weiterverarbeiten muss.

Das sieht in etwa so aus:

Code: Alles auswählen

def eingabe_hauptspeise(id):
    db = pyodbc.connect("dsn=MySQL_liste")
    cursor = db.cursor()
    if len(id) == 1:
        id = id[0]
        sql = ("""SELECT * FROM hauptspeisen WHERE id = '%s'"""% (id))
        global id_1
        global hauptspeise
        global brutto
        global netto
        global bestellung
        for row in cursor.execute(sql):
            id_1 = {}
            hauptspeise = row.hauptspeise
            brutto = row.brutto
            netto = row.netto
            id_1 = {"hauptspeise":hauptspeise, "brutto":brutto, "netto":netto}
            bestellung = id_1.values()      
            print bestellung[1], bestellung [0], bestellung [2]
            db.commit()
Wenn ich dieses Modul importiere, scheinen diese Variablen aber nicht global auf, d.h. NameError.

Designfehler?
Zap
User
Beiträge: 533
Registriert: Freitag 13. Oktober 2006, 10:56

Warum muss das ganze mit globalen Variablen umgesetzt werden!?
Es wäre doch sauberer wenn deine Funktion die Daten als Liste von Dictionaries
oder ähnliches zurück gibt.

Edit:
---------------
Allgemein zu deinem Code:
- Der Funktionsname "eingabe_hauptspeise" passt irgendwie nicht zu dem was die Funktion macht.
- "id" scheint ja irgendwie eine Sequenz von Werten zu sein, auch hier passt der Name nicht
- schmeisse alles was global ist raus und baue dir eine sinnvolle Struktur die du per return zurück geben kannst.
- ein db.commit() macht bei einer SELECT query wenig Sinn, ein close() wäre hingegen angebracht.
ms4py
User
Beiträge: 1178
Registriert: Montag 19. Januar 2009, 09:37

Zap hat geschrieben: - "id" scheint ja irgendwie eine Sequenz von Werten zu sein, auch hier passt der Name nicht
Außerdem überschreibt es ein Builtin...
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Außerdem erscheint der Datenbank connect deplatziert. Zudem läuft er ohne das Abfangen von Exceptions ab. Ich würde den schon in eine connect_db()-Funktion auslagern. Vermutlich bleibt es ja nicht bei der einen Abfrage und damit kann man ihn dann wiederverwenden...
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Außerdem:

- Du solltest Anfragen nie wie in Zeile 7 zusammensetzen, die execute-Methode hat einen zweiten Parameter dafür. Andernfalls handelst du dir leicht die Möglichkeit für SQL-Injections ein.
- Zeile 14 ist überflüssig. Du musst vor der Verwendung nichts deklarieren.
- Mit einer vernünftigen Anfrage könntest du die Zeilen 15 bis 18 zu einer zusammenfassen.
- Ist dir bewusst, dass die Reihenfolge in Dictionaries nicht unbedingt beibehalten wird?
- Wenn du Indizes verwendest, gehört vor diese keine Leerzeichen. Diese beziehen sich immer auf den vorausgegangenen Ausdruck und stehen nicht für sich alleine.
- Du solltest über Konstanten für das Dictionary nachdenken.
- "eingabe_hauptspeise" ist ein sehr seltsamer Name für eine Funktion, wo doch nichts eingegeben wird.
- Was passiert, wenn len(id) nicht gleich 1 ist? Diesen Fall behandelst du gar nicht.

Vieles andere wurde ja schon gesagt.
Das Leben ist wie ein Tennisball.
DasIch
User
Beiträge: 2718
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

ice2k3 hat geschrieben:Außerdem überschreibt es ein Builtin...
Das nutzt du nicht ernsthaft als Argument? Ich überschreibe ständig builtins, solange man es nur lokal macht ist dass absolut kein Problem.
m6T
User
Beiträge: 3
Registriert: Dienstag 20. Oktober 2009, 11:46

Danke mal für die Tipps und Verbesserungsvorschläge.

Die Funktion eingabe_Hauptspeise hat den Sinn dass eine ID des Essens (die ID's werden vorher über eine andere Funktion ausgegeben) der Funktion übergeben wird, und die Funktion das Essen über die ID ermittelt und den Variablen zuweist. Der Input geschieht im Hauptprogramm über einen input().

Die Funktionen kümmert sich auch um Fälle wenn len(id) länger als 1 ist, jedoch hab ich die anderen Teile weggelassen da sie im grunde gleich aufgebaut sind wie der Teil wenn len(id) = 1.

Ich werd mal sehen dass ich die Tipps umsetze und versuche das ganze über ein Dictionary zu regeln. Danke soweit!
Zap
User
Beiträge: 533
Registriert: Freitag 13. Oktober 2006, 10:56

DasIch hat geschrieben:
ice2k3 hat geschrieben:Außerdem überschreibt es ein Builtin...
Das nutzt du nicht ernsthaft als Argument? Ich überschreibe ständig builtins, solange man es nur lokal macht ist dass absolut kein Problem.
Ich bin schon der Meinung das man einen Anfänger darauf hinweisen sollte.
Ihm muss zumindest bewusst sein das sowas ein paar Zeilen später ein selbst gelegter Stolperstein sein kann.

Ich überschreibe in der Regel keine builtins da erstens das Syntaxhighlighting der IDE irreführend ist und
zweitens seit geraumer Zeit pylint in meinen Projekten im Einsatz ist.
Und ich finde es gut das auch dieser einen darauf aufmerksam macht.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

@DasIch: Ich glaube Dir natürlich, dass Du häufiger selber built-ins überschreibst. Aber glaubst Du denn auch, dass man das auch noch "empfehlen" sollte? :shock:

@m6T:
Was genau steht denn nun in einer "id"? Wieso kann len(id) > 1 sein? Wenn ja, wäre das ja ein Iterable und der Name "id" wäre auch noch unpassend.
Ist das eine GUI-Anwednung? Wenn nein, soltest Du unter Python < 3.x immer raw_input() statt input() nutzen.
DasIch
User
Beiträge: 2718
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

Hyperion hat geschrieben:@DasIch: Ich glaube Dir natürlich, dass Du häufiger selber built-ins überschreibst. Aber glaubst Du denn auch, dass man das auch noch "empfehlen" sollte? :shock:
Ich empfehle builtins nicht um jeden Preis nicht zu überschreiben.

Das Ziel beim schreiben von Code sollte Lesbarkeit und Verständnis sein und wenn Regeln wie diese oder PEP8 dieses Ziel in einem bestimmten Kontext nicht erreichen muss ich Ausnahmen oder sogar neue Regeln schaffen.

Desweiteren erlaubt eine gute IDE dass Syntax Highlighting für bestimmte Dinge abzuschalten, ich lasse zum Beispiel builtins nicht highlighten. Wobei es natürlich besser wäre semantisches Highlighting zu haben dann stellt sich so ein Problem gar nicht erst.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

DasIch hat geschrieben: Ich empfehle builtins nicht um jeden Preis nicht zu überschreiben.

Das Ziel beim schreiben von Code sollte Lesbarkeit und Verständnis sein und wenn Regeln wie diese oder PEP8 dieses Ziel in einem bestimmten Kontext nicht erreichen muss ich Ausnahmen oder sogar neue Regeln schaffen.
Hm... dann müßte "file" aber fast immer überschrieben werden. Und das Verständnis könnte durchaus darunter leiden, wenn man nicht das lokale Konstrukt auf den ersten Blick sieht, sondern eben das built-in.
derdon
User
Beiträge: 1316
Registriert: Freitag 24. Oktober 2008, 14:32

Hyperion hat geschrieben:Hm... dann müßte "file" aber fast immer überschrieben werden.
Für Dateinamen nutze ich file_name, für Dateiobjekte file_object oder einfach nur f. file allein ist mir zu mehrdeutig.
Benutzeravatar
jbs
User
Beiträge: 953
Registriert: Mittwoch 24. Juni 2009, 13:13
Wohnort: Postdam

In PEP 8 steht, dass man Ausnahmen machen darf, wenn es der verständlichkeit dient.

Und ich meine an

Code: Alles auswählen

...
member[id]
...
sollte verständlich sein.

Zur Not geht ja noch: ``__builtin__.id``, was natürlich wieder unsauber ist.


P.S.: Ich will jetzt nicht zum Überschreiben von builtins aufrufen :). Man sollte sie natürlich vermeiden, wenn es nicht klarer wird.
[url=http://wiki.python-forum.de/PEP%208%20%28%C3%9Cbersetzung%29]PEP 8[/url] - Quak!
[url=http://tutorial.pocoo.org/index.html]Tutorial in Deutsch[/url]
DasIch
User
Beiträge: 2718
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

Hyperion hat geschrieben:Hm... dann müßte "file" aber fast immer überschrieben werden.
``file`` sollte man sowieso nicht benutzen es sei den man erbt davon.
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

DasIch hat geschrieben:
Hyperion hat geschrieben:Hm... dann müßte "file" aber fast immer überschrieben werden.
``file`` sollte man sowieso nicht benutzen es sei den man erbt davon.
Welche builtins überschreibst du denn üblicherweise? Weil ich überschreibe eigentlich nie welche, was auch daran liegt dass die Namen idR sowieso selten als gute Variablennamen taugen.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
DasIch
User
Beiträge: 2718
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

Leonidas hat geschrieben:
DasIch hat geschrieben:
Hyperion hat geschrieben:Hm... dann müßte "file" aber fast immer überschrieben werden.
``file`` sollte man sowieso nicht benutzen es sei den man erbt davon.
Welche builtins überschreibst du denn üblicherweise?
``id`` und ``file`` als einfache Namen. ``all`` überschreibe ich manchmal mit einer Funktion die False zurück gibt wenn das iterable leer ist, wenn ich mich dabei erwische mehrmals ``all(foo) and foo`` zu schreiben.

EDIT: Fehler korrigiert, danke BlackJack
Zuletzt geändert von DasIch am Dienstag 20. Oktober 2009, 20:34, insgesamt 1-mal geändert.
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

DasIch hat geschrieben:
Leonidas hat geschrieben:Welche builtins überschreibst du denn üblicherweise?
``id`` und ``file`` als einfache Namen. ``all`` überschreibe ich manchmal mit einer Funktion die False zurück gibt wenn das iterable leer ist, wenn ich mich dabei erwische mehrmals ``all(foo) or foo`` zu schreiben.
"file" finde ich einen äußerst unglücklichen Namen aus. Dieser sagt genau nichts aus. Da würde ich lieber einen Namen wählen, welcher Aussagt, was in der Datei drin ist, oder was rein soll.
"all" mit einem anderen Verhalten zu überschreiben ist auch sehr unglücklich. Ich würde nicht erwarten, dass "all" auf einmal bei leeren Listen ein anderes Ergebnis liefert.
Das Leben ist wie ein Tennisball.
BlackJack

@DasIch: Bist Du sicher, dass Du nicht ``foo and all(foo)`` meintest!? Denn ``all(foo) or foo`` ergibt bei leerem `foo` auch `True`.
DasIch
User
Beiträge: 2718
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

EyDu hat geschrieben:"file" finde ich einen äußerst unglücklichen Namen aus. Dieser sagt genau nichts aus. Da würde ich lieber einen Namen wählen, welcher Aussagt, was in der Datei drin ist, oder was rein soll.
Wenn ich in ``Config.__init__`` eine Datei öffne und parse muss ich die nicht auch noch ``config_file`` nennen, dass ist redundant.

@Blackjack: Jetzt nicht mehr :oops:
sma
User
Beiträge: 3018
Registriert: Montag 19. November 2007, 19:57
Wohnort: Kiel

Um mal nach all diesem Gerede über Namen auf die eigentliche Frage zurückzukommen:
m6T hat geschrieben:Designfehler?
Ja.

Das ganze sollte so aussehen:

Code: Alles auswählen

hauptspeise, brutto, netto = lies_hauptspeise("whatever")
...
def lies_hauptspeise(whatever):
    ...
    return row.hauptspeise, row.brutto, row.netto
Noch besser wäre, ein Objekt mit passenden Attribute zu benutzen.

Stefan
Antworten