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.
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

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: 227
Registriert: Donnerstag 17. Dezember 2015, 12:17

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: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

@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

@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: 227
Registriert: Donnerstag 17. Dezember 2015, 12:17

@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: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

@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: 227
Registriert: Donnerstag 17. Dezember 2015, 12:17

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

@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: 227
Registriert: Donnerstag 17. Dezember 2015, 12:17

@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: 3843
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

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
harryberlin
User
Beiträge: 227
Registriert: Donnerstag 17. Dezember 2015, 12:17

@noisefloor
wenn z.b. ein thread in einer while schleife ist, die beendet werden soll(ggf. auch durch nen anderen thread). dafür möchte ich die variable auf True setzen.
zum style guide und pep:
ja ich weiß, wer meine vorgeschichte nicht kennt, wird es als "assi" auffassen.
nur ich wurde schon zu genüge darauf hingewiesen.
Zuletzt geändert von harryberlin am Dienstag 9. Februar 2016, 22:19, insgesamt 1-mal geändert.
empty Sig
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

@harryberlin: Threads dürfen gar keine Variablen teilen. Dafür gibt es spezielle Datenstrukturen (Events, Queues, Semaphoren).
BlackJack

@harryberlin: Ich habe mal kurz reingeschaut und kämpfe gerade damit nicht PEP8 als Lektüre zu empfehlen, denn das soll ich ja nicht. ;-) Ernsthaft, da ist mir zu viel ``global`` und zu viele Sternchen-Importe drin um mich damit näher auseinandersetzen zu wollen.
harryberlin
User
Beiträge: 227
Registriert: Donnerstag 17. Dezember 2015, 12:17

oh wahnsinn. ich hab nen code der läuft, aber eigentlich absoluter schrott ist....
das wird ja ewig dauern, bis ich da was vernünftiges draus gemacht hab.
ewig, weil ich meine meiste zeit mit Brötchenverdienen verbringe.

ja, die sternchen...
ich werd echt mal schaun, dass ich ein py file mit klassen draus mache.
empty Sig
Benutzeravatar
pillmuncher
User
Beiträge: 1482
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

harryberlin hat geschrieben:oh wahnsinn. ich hab nen code der läuft, aber eigentlich absoluter schrott ist....
das wird ja ewig dauern, bis ich da was vernünftiges draus gemacht hab.
ewig, weil ich meine meiste zeit mit Brötchenverdienen verbringe.
Wie die meisten hier.

Es geht einfach darum, dass du dir dein Leben einfach machst, indem du Code schreibst, der einfach zu handhaben ist. Sternchen-Importe sind schlecht, weil dann nicht klar ist, welcher Name aus welchem Modul kommt. Wenn man dagegen Stenchen-Importe vermeidet und statt dessen explizit hinschreibt, welche Namen man importiert, sieht man sofort, wo ein Name herkommt und muss nicht raten.

Globale Variablen sind schlecht, weil man damit seinen Systemzustand über den gesamten Code verteilt. Übergänge von einem zu einem anderen Zustand können dann prinzipiell überall und zu jeder Zeit geschehen. Man muss also zB. bei jeder Zuweisung den gesamten Code im Kopf behalten, damit man alle Implikationen dieser Zuweisung verstehen kann. Insbesondere bei nebenläufigen Programmen ist das oft gar nicht möglich. Statt globale Variablen verwendet man dabei lieber Events oder Queues, die man den Threads bei der Initialisierung als Argumente übergibt. Darüber können dann die Threads kommunizieren, ohne dass ihnen irgendeine andere Codestelle ein Bein stellt.

Wirklich, es geht nicht darum, dass du Code schreibst, der irgendeinem abstrakten Schönheitsideal enspricht, bloß weil wir hier alle Ästheten sind, die aus bloßer Spießigkeit auf diesem Ideal beharren, sondern es geht darum, dass du dir dein Leben einfach machst.

Die Geschichte vom Metzger Ding aus dem Zhuangzi (AKA "Das wahre Buch vom Südlichen Blütenland") illustriert diesen Sachverhalt.

Ebenso "The Big Lebowski" von den Cohen-Brüdern.

Sagte ich bereits, dass du dir dein Leben einfach machen sollst?
In specifications, Murphy's Law supersedes Ohm's.
Benutzeravatar
pillmuncher
User
Beiträge: 1482
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

Zhuangzi, Buch III - Der Koch: http://www.zeno.org/Philosophie/M/Zhuan ... .+Der+Koch

Nach Laozi, von dem das Daodejing (Tao Te King) stammt, war Zhuangzi (auch Tschuang Tzu, Dschuang Dsi, Chuang Tse) der zweite große Denker des Daoismus. Die Überseztung in dem Link oben stammt von Richard Wilhelm, 1912. Er übersetzt Dào (道) als SINN. Es heißt aber Weg, sowohl im Sinne von Straße als auch von Weise etwas zu tun. Wilhelm hat sich auch nicht von allen abendländischen (lies: christlichen; er war Missionar) Vorstellungen über die Bedeutung der Worte freigemacht und auch nicht von allen zeittypischen Vorstellungen über China. Trotzdem kann man die Geschichte vom Metzger/Koch Ding gut verstehen, IMO.
In specifications, Murphy's Law supersedes Ohm's.
Benutzeravatar
pillmuncher
User
Beiträge: 1482
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

Noch einer, weil ich den Beitrag nicht mehr ändern kann.

Bevor mich jemand anmopst, weil er/sie meint, Dào sei hier offtopic:

The Tao of Programming, 1.4:
The wise programmer is told about Tao and follows it. The average programmer is told about Tao and searches for it. The foolish programmer is told about Tao and laughs at it.

If it were not for laughter, there would be no Tao.

The highest sounds are hardest to hear. Going forward is a way to retreat. Great talent shows itself late in life. Even a perfect program still has bugs.
In specifications, Murphy's Law supersedes Ohm's.
harryberlin
User
Beiträge: 227
Registriert: Donnerstag 17. Dezember 2015, 12:17

Auf jeden Fall, danke an euch.

Dass man Sternchen nicht macht, da hab ich letztens drüber gelesen.
Im Grunde benötige ich den zustand übers ganze System.
und wenn ich boolsche variablen sinnvoll benenne, sollte ein nachvollziehen nicht all zu schwer sein, bei nur True oder False.

Was mir etwas Kopfzerbrechen bereitet, wenn ich Zustände als Argument an einen Thread übergebe, das ist ja dann erstmal statisch in dem Thread. Ändert sich dann der Zustand, dann hat es keine Wirkung auf die Funktion im Thread. Oder ist das nicht so, bleibt die Verbindung Argument und Zustand erhalten, und wirkt sofort bei einer Änderung?
empty Sig
Antworten