global vermeiden

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.
RedGargoyle
User
Beiträge: 3
Registriert: Mittwoch 13. Januar 2016, 13:12

Mittwoch 13. Januar 2016, 19:00

@ DasIch
Puhh, ich glaube über die Antwort muss ich erst einmal meditieren :-)
Aber klar, kleckern mag ich echt nicht.

Trotzdem danke!


@ BlackJack
So langsam sehe ich ein, dass die Variante mit global bei Verschachtelungen zu sehr unübersichtlichem Code (und somit auch leicht zu Fehlern) führt.
Aber ich will trotzdem nochmal nachfragen: Gibt es, in der Form, in der ich die beiden Varianten angegeben habe, einen offensichtlichen Unterschied?
BlackJack

Mittwoch 13. Januar 2016, 19:50

@RedGargoyle: Variante 1 ist offensichtlich schlechter als Variante 2, aus den ganzen Gründen aus denen ``global`` Böse™ ist.
harryberlin
User
Beiträge: 189
Registriert: Donnerstag 17. Dezember 2015, 12:17

Dienstag 9. Februar 2016, 18:02

Um das Thema global (4.) aus dem Thread viewtopic.php?f=1&t=37842&start=30 noch zu beenden.
Habe nun auch noch den weiteren Ausdruck für Eigenschaften einer Klasse gefunden, nämlich Attribut.

Ich würde es nun mit einer sogenannten variablen Klasse lösen. Z.B.

Code: Alles auswählen

class VarHandler:
    def __init__(self):
        self.state1 = False
        self.state2 = False
        self.state3 = False
        self.var1 = None
   
variable = VarHandler()
variable.state1 = True
print variable.state1
Gibt es noch bessere Lösungen, oder findet ihr das gut?

Komisch, warum geht die Codebox nicht?
empty Sig
BlackJack

Dienstag 9. Februar 2016, 18:12

@harryberlin: Codebox ist gerade kaputt. :-(

Das was Du da jetzt geschrieben hast ist ja immer noch eine globale Variable, nämlich `variable`. Und ob das nun Sinn macht die Variablen als Attribute zu einem Objekt zusammen zu fassen hängt davon ab was die eigentlich bedeuten und ob die sinnvoll zusammengehören. Und wenn die zusammengehören, dann gibt es in der Regel auch Methoden die ebenfalls zu den Daten gehören.

Das was da steht kann man ohne Klasse und ohne globale Variablen so schreiben:

Code: Alles auswählen

#!/usr/bin/env python
# coding: utf8
from __future__ import absolute_import, division, print_function


def main():
    state1 = False
    state2 = False
    state3 = False
    var1 = None

    state1 = True
    print(state1)


if __name__ == '__main__':
    main()
harryberlin
User
Beiträge: 189
Registriert: Donnerstag 17. Dezember 2015, 12:17

Dienstag 9. Februar 2016, 18:27

ja, ich brauche es auch global.
so besser?

Code: Alles auswählen

class VarHandler:
    def __init__(self):
        self.state1 = False
        self.state2 = False
        self.state3 = False
        self.var1 = None

variable = VarHandler()

def main():
    variable.state1 = True
    print variable.state1

if __name__ == 'main':
    main()
kann man in die klasse auch functionen für set und get einbauen, wo man direkt die variable als argument übergibt?
mir würde jetzt die möglichkeit einfallen, das argument variable als string zu übergeben und mit if zu parsen, aber geht das auch einfacher.
in etwa so:

Code: Alles auswählen

    def set(self,variable,value):
        self.variable = value

    def get(self,varaible):
        return self.variable
wobei, wäre eigentlich überflüssig. weil man die vars einfach mit = setzen oder holen kann.
empty Sig
Benutzeravatar
cofi
Moderator
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Dienstag 9. Februar 2016, 18:43

Das Problem an globalen Variablen ist nicht `global`, sondern dass sie eben globale Variablen sind.

Damit hat man das Problem, dass verschleiert wird wo der Wert geaendert wird und so der Code schwerer zu verstehen ist.
So wie es jetzt ist, ist es im Grunde _noch_ schlechter als mit `global`, weil dort wenigstens die Stellen deklariert werden, die den Wert aendern.

Die einzige Loesung zu dem Problem ist die Werte lokal zu erstellen und als Parameter an Funktionen zu uebergeben, die den geaenderten Zustand eventuell zurueckgeben.
Das ist allerdings ein Architekturproblem bei dem man ohne den verwendeten Aufbau und Code nicht konkret helfen kann.
harryberlin
User
Beiträge: 189
Registriert: Donnerstag 17. Dezember 2015, 12:17

Dienstag 9. Februar 2016, 19:04

OK. D.h. wenn ich mit mehreren Funktionen arbeite, die unabhängig auf die variablen zugreifen müssen, dann ist global zulässig?
Denn der Zustand der Variable muss gepuffert werden. Und entsprechend welche funktion getriggert wird, muss sie abhängig von der variable agieren.

oder meinst du ich soll die variablen als argument für die funktion übergeben.
z.B.

Code: Alles auswählen

def (arg1, arg2, state1, state2, state3):
    #do all the things with the variables or change them
    .....
finde ich dann aber auch recht umständlich.
empty Sig
Sirius3
User
Beiträge: 7586
Registriert: Sonntag 21. Oktober 2012, 17:20

Dienstag 9. Februar 2016, 19:34

@harryberlin: fünf Argumente für eine Funktion sind eigentlich eher selten. Wie die beste Lösung ist, ist, wie cofi schon geschrieben hat, aber von der konkreten Aufgabe ab. Bei so allgemeinen arg1, arg2 kann man halt nicht wirklich weiterhelfen.
BlackJack

Dienstag 9. Februar 2016, 19:55

@harryberlin: Gerade wenn mehrere Funktionen auf mehrere Variablen zugreifen ist ``global`` nicht zulässig, denn genau das ist doch das Chaos was man vermeiden möchte, wenn man das Programm verstehen möchte ohne wirklich immer das ganze Programm im Kopf zu haben weil man sonst nicht weiss welche Funktion von was abhängt und was ändert. Funktionen hat man doch um eine Einheit zu haben die man unabhängig vom Rest des Programms betrachten und nachvollziehen kann. Die man testen und wiederverwenden kann. Die man auch einfach in ein anderes Modul verlagern kann. Das geht alles nicht wenn man globalen Zustand berücksichtigen muss.
harryberlin
User
Beiträge: 189
Registriert: Donnerstag 17. Dezember 2015, 12:17

Dienstag 9. Februar 2016, 20:12

@sirius3:
ich würde meinen code schon gern mal zeigen.
nur zeigte mir die erfahrung, dass mich das eher nicht zum ziel bringt.
denn mein code ist grottig, das weiß ich.
um ihn zu verbessern, bin ich ja hier. also muss ich leichte beispiele für teilabschnitte bringen.
anders sehe ich keinen weg. bzw. wird sich dem auch keiner annehmen.
und würde zu dem nicht in den thread hier passen, bzw. sprengen.

arg1, arg2 sind argumente für die funktion. state.. wären dann die globalen variablen.

jedoch was mir hilft, sind konkrete aussagen.
cofi hat geschrieben:
1. es ist schlimmer als global
2. als parameter übergeben
3. man müsste den code kennen
auf welche dieser aussagen beziehst du dich?

@blackjack:
ja, aber wenn die funktion durchlaufen ist, bleibt der zustand doch nicht erhalten.
oder liege ich da falsch?

z.B.

Code: Alles auswählen

def set_var(state):
    var = state

def get_var():
    return var
    
def main():
    set_var(True)
    print get_var()
    
if __name__='__main__':
    main()
       
das funktioniert doch nicht.
empty Sig
Sirius3
User
Beiträge: 7586
Registriert: Sonntag 21. Oktober 2012, 17:20

Dienstag 9. Februar 2016, 20:53

@harryberlin: ich meinte die dritte Aussage. Wobei natürlich auch beide anderen Aussagen stimmen. Der Sinn einer Funktion ist es ja gerade, dass wenn sie durchlaufen ist, der Zustand auf seine Rückgabewerte reduziert wird. Damit kann man lesbaren, testbaren, wiederverwendbaren und funktionierenden Code schreiben.
harryberlin
User
Beiträge: 189
Registriert: Donnerstag 17. Dezember 2015, 12:17

Dienstag 9. Februar 2016, 21:09

wo holt die get-funktion die variable dann her, wenn sie nicht durch parameterübergabe erzeugt werden kann?

z.B. ein licht_an. irgendwann später kommt ein event, mach_das_licht_aus. aber nur wenn das lichtanist.
das licht ist doch ein globaler zustand.
ist jetzt ein etwas blödes beispiel, weil man jetzt wieder sensoren einbauen kann, die abfragen ob das licht an ist.
gehen wir mal davon aus, es gibt nur den einen zustand.

oder vllt der zusatz, ich bin das licht.
empty Sig
BlackJack

Dienstag 9. Februar 2016, 21:14

@harryberlin: Man kann schlecht sinnvolle Vorschläge zum strukturieren von Code machen, dessen Semantik man nicht kennt. Niemand kann Dir bei so supergenerischen Namen wie arg1, var2, state3 und ohne die Operationen zu kennen, sagen wie man da was am besten zusammenfasst. Was man allgemein sagen kann, ist das globaler Zustand die ganzen bereits genannten Nachteile mit sich bringt.

Wenn eine Funktion Zustand ändern soll, dann muss sie entweder den Folgezustand zurückgeben, oder tatsächlich einen Zustand ändern, nur halt bitte keinen globalen und am besten dann auch nicht als Funktion, denn wenn sie einen Zustand ändert, gehört sie wahrscheinlich so eng zu dem Zustand, dass sie mit den Daten zusammen zu einem Objekt zusammengefasst werden könnte. Deine beiden Beispielfunktionen sind da etwas sinnfrei, also mal ein (total simples) Beispiel bei dem der Zustand verändert wird:

Code: Alles auswählen

def negate(state):
    return not state
   

def main():
    state = True
    state = negate(state)
    print state
Wieso sollte der Zustand nicht durch ein Argument übergeben werden können?
harryberlin
User
Beiträge: 189
Registriert: Donnerstag 17. Dezember 2015, 12:17

Dienstag 9. Februar 2016, 21:46

@blackjack
ich glaub so langsam fällt der groschen.
wenn ich die variablen in der main() drin setze, dann sollte es zulässig sein.
brauche dann halt einige threads, weil so vieles gleichzeitig läuft.
und übergabe müsste per argument(auch wenn es viele sind) erfolgen.

ich schick dir meine source mal per pn. aber bitte keine belehrungen ala style guide oder pep.
empty Sig
Benutzeravatar
noisefloor
User
Beiträge: 2359
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: Görgeshausen
Kontaktdaten:

Dienstag 9. Februar 2016, 22:00

Hallo,
brauche dann halt einige threads, weil so vieles gleichzeitig läuft.
Bei Threads wird das aber viel komplizierter, weil man dann noch schwerer den Überblick behält, wann wer was ändert. Und eigentlich nimmt man Threads dann, wenn "Dinge" gleichzeitig, aber unabhängig voneinander laufen sollen.

_Welche_ Daten willst (musst?) du denn allen Threads verfügbar machen?
aber bitte keine belehrungen ala style guide oder pep.
Oh oh... mit der Einstellung kommst du hier nicht weit ;-)

Gruß, noisefloor
Antworten