Globale Namen definieren ???

Code-Stücke können hier veröffentlicht werden.
Sirius3
User
Beiträge: 18272
Registriert: Sonntag 21. Oktober 2012, 17:20

Warum nimmt `ControlAPairOfPins` Strings, wenn Du doch sowieso wieder alles in Ints umwandelst?
Das ganze ließe sich noch kürzer schreiben, wenn man statt der if-Abfragen direkt die Bedingung als Parameter einsetzt:

Code: Alles auswählen

def ControlAPairOfPins(FirstPin,FirstState,SecondPin,SecondState):
    GPIO.output(int(FirstPin), FirstState == "1")
    GPIO.output(int(SecondPin),SecondState == "1")
als nächstes solltest Du Dir angewöhnen, Dich an PEP-8 zu halten. Vor allem die Einrückung von 4 Leerzeichen.
Dann selltest Du `global` vermeiden, indem Du die Werte per `return` an den Aufrufer zurückgibst.
Zappelmann
User
Beiträge: 27
Registriert: Freitag 23. Mai 2014, 11:01

Sirius3 hat geschrieben:als nächstes solltest Du Dir angewöhnen, Dich an PEP-8 zu halten. Vor allem die Einrückung von 4 Leerzeichen.
Dann selltest Du `global` vermeiden, indem Du die Werte per `return` an den Aufrufer zurückgibst.
hmmmm erstmal danke für deine Anregung, aber bitte gibt es das auch in deutsch zu lesen, denn irgendwie ist ein so hochkonzentriertes Englisch nicht so ganz mein Ding....
Was die Einrückung von 4 Leerzeichen angeht, jo eigentlich versuche ich mich schon sehr daran zu halten. Aber ich hab den Bereich gefunden wo es nicht der Fall ist ich werde das dann korrigieren. Was die Codeänderung angeht. Ich werde drüber nachdenken und es mal austesten. Wenns funzt werde ich den Code daraufhin anpassen. Ja das mit dem return hab ich auch gelesen wegen Wertübergabe. Aber ich hab dabei halt auf nen Error mit global name define reagiert gehabt und deswegen das ganze ja hier überhaupt angefangen zu schreiben.

Aber ich werde mal weiter Versuche damit starten und schauen ob ich das richtig umgesetzt bekomme. Aber dieses PEP-8 Das muss ich erstmal verstehen was du mir damit sagen möchtest. Dann dahinter bin ich jetzt bisher noch nicht gekommen auser das es sich scheinbar um ein Style für Python Code geht. Aber vielleicht hast du da ja was ähnlihces was es auch auf deutsch gibt. Ansonsten werde ich später mal selber googlen.

MFG

Zappelmann
Zappelmann
User
Beiträge: 27
Registriert: Freitag 23. Mai 2014, 11:01

Zappelmann
User
Beiträge: 27
Registriert: Freitag 23. Mai 2014, 11:01

So das mit dem starten und stoppen des Scriptes über einen Taster hab ich schon gelöst. Ich hab dafür aber nen Schalter genommen und nen Taster zum testlauf. Jetzt konnte ich auch endlich mal das Script direkt in den Bootvorgang einbinden. Ohne das der direkt losfährt. Klappt wunderbar.

MFG

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

Zappelmann hat geschrieben:Das hättet ihr aber auch direkt schreiben können das es so einfach ist ^^.
Haben wir doch. Aber du verwendest noch immer gloabl-Anweisungen.
Zappelmann hat geschrieben:Aber ich werde mal weiter Versuche damit starten und schauen ob ich das richtig umgesetzt bekomme. Aber dieses PEP-8 Das muss ich erstmal verstehen was du mir damit sagen möchtest. Dann dahinter bin ich jetzt bisher noch nicht gekommen auser das es sich scheinbar um ein Style für Python Code geht. Aber vielleicht hast du da ja was ähnlihces was es auch auf deutsch gibt.
Ja, PEP 8 ist ein Style Guide an den du dich unbedingt halten solltest. Zumindest dann, wenn andere deinen Code lesen sollen. Was hier ja der Fall ist. Ansonsten solltest du einfach die Idee vergessen, dass es Dokumentation auf Deutsch gibt. Um Englisch wirst du nicht herumkommen.
Das Leben ist wie ein Tennisball.
lackschuh
User
Beiträge: 281
Registriert: Dienstag 8. Mai 2012, 13:40

Hallo

Ich hab auch eine kleine Frage bzgl. globale Variablen. Was wäre die 'richtige' Alternative zu folgendem Beispiel:

Code: Alles auswählen

import time

count = 0

def counter():
    while True:
        count = count + 1
        print count
        time.sleep(1)

counter()

Code: Alles auswählen

UnboundLocalError: local variable 'count' referenced before assignment
so?

Code: Alles auswählen

import time

count = 0

def counter(count):
    while True:
        count = count + 1
        print count
        time.sleep(1)

counter(count)
BlackJack

@lackschuh: Eher so:

Code: Alles auswählen

import time

def counter():
    count = 0
    while True:
        count = count + 1
        print count
        time.sleep(1)

def main():     
    counter()


if __name__ == '__main__':
    main()
Beziehungsweise:

Code: Alles auswählen

import time
from itertools import count
 

def counter():
    for i in count(1):
        print i
        time.sleep(1)
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Das kommt drauf an, was du eigentlich willst. Die beiden Fragmente tun schliesslich nicht dasselbe: #1 benutzt und veraendert die globale Variable (wenn man `global` hinzufuegt) #2 benutzt nie eine globale Variable und der Parameter `count` ist nur der Startwert.

Wenn du beabsichtigst, dass sich das globale `count` veraendert, dann gibt es keine richtige Alternative. Das Problem ist schliesslich nicht die `global` Anweisung sondern die globale Variable.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Als erstes würde man ``count`` als Konstante *groß* schreiben, also ``COUNT``.

Und ja, man sollte an Funktionen Parameter übergeben - dabei kann man dann aber auch gerne Default-Werte statt Konstanten setzen:

Code: Alles auswählen

def counter(start=0):
    # usw.
Die Frage ist dabei ja eher, ob man einen Wert *mehrfach* benötigt. Falls ja, kann man gerne eine Konstante nehmen, falls nein, imho besser einen Default-Parameter.

"Konstanten" sind hier natürlich reine Konvention aufgrund der Schreibweise!

Idiomatischer wäre es imho auch so:

Code: Alles auswählen

from itertools import count
from time import sleep

def counter(start=0):
    for c in count(start):
        print(c)
        sleep(1)
Hier böte es sich eher / zudem an, die Wartezeit als Konstante zu hinterlegen oder auch als (Default)-Parameter zu übergeben.

Och menno, BJ war schneller :-D
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
lackschuh
User
Beiträge: 281
Registriert: Dienstag 8. Mai 2012, 13:40

Danke für die Infos. Vielleicht war das Beispiel nicht ganz das richtige. Angenommen ich definiere zu Beginn des Programms eine Variable mir dem Wert 0 (oder was auch immer). Diese Variable taucht aber nachfolgend in mehreren Funktionen und Klassen auf. Dann wäre nach BlackJack's Beispiel es so, dass man innerhalb einer jeden Funktion die Variable neu setzt.(?)

Ich beziehe mich auf das hier.

mfg
BlackJack

@lackschuh: Das ist immer noch alles sehr missverständlich formuliert. Was heisst zu Beginn des Programms? Im Quelltext auf Modulebene? Nein, da definiert man keine Variablen. Die Variable taucht auch nicht in mehreren Funktionen einfach so auf. Werte, ausser Konstanten, betreten Funktionen als Argumente. Welchen Wert der Name lokal dabei bekommt ist unabhängig davon an welchen Namen er bei einem Aufrufer gebunden ist.
Benutzeravatar
snafu
User
Beiträge: 6867
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

@lackschuh: Wenn die Variable nicht verändert wird oder wenn die Variable als gemeinsamer Startwert gilt, dann kann man sie situationsabhängig als Konstante definieren. Im Falle eines Startwertes sollte man den Startwert an einen neuen Namen binden und Veränderungen dann mit diesem neuen Namen durchführen. Zwar ist der neue Name zunächst nur eine Referenz auf das selbe Zahl-Objekt, welches auch von der Konstante referenziert wird, aber nach einer Rechenoperation wird ja ohnehin ein neues Zahl-Objekt als Resultat erzeugt und dieses wird dann halt neu an den zusätzlichen Namen gebunden (ich hoffe du kannst mir bis hier noch folgen). Somit kommt man gar nicht auf die Idee, irgendwas mit `global` hinzupfuschen. Wie gesagt: Das alles immer unter der Annahme, dass sich andere Funktionen ebenfalls nur für den Startwert und nicht für den veränderten Wert interessieren. Falls letzteres zutrifft, dann handelt es sich definitiv um keine Konstante, sondern um eine tatsächlich veränderliche Variable, dessen Definition man auf Modulebene vermeiden sollte.
lackschuh
User
Beiträge: 281
Registriert: Dienstag 8. Mai 2012, 13:40

Hallo

Danke für die Infos.
Also zB habe ich Startwerte oder Flags, welche zu Beginn im Quelltext den Wert '''0''' haben. Wie könnte man es anhand des unteren Beispiels erklären, wie global zu vermeiden wäre?. Die Erklärung von snafu verwirrt mich leicht bzw. ich kapier sie wohl nicht ganz :K

Code: Alles auswählen

status = 0

class EmailThread(threading.Thread):
    
    def __init__(self):
        threading.Thread.__init__(self)
        
    def run(self):
        global status
        while True:
		    #mach was
            if habe_mail == 1: # status wird auf 1 gesetzt
                status = 1
				
def main():
    global status
    while True:
        if status == 0:
            pass # mach nichts
        elif status = 1:
        # Aufruf weiterer Funktionen
Vielen Dank
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Durch eine Queue-Objekt, welches du aus der main-Funktion dem E-Mail-Thread übergibst. Dann sparst du dir auch das Busy-Waiting und treibst deine Stromrechnung nicht in ungeahnte Höhen.
Das Leben ist wie ein Tennisball.
Benutzeravatar
pillmuncher
User
Beiträge: 1530
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

EyDu hat geschrieben:...sparst du dir auch das Busy-Waiting und treibst deine Stromrechnung nicht in ungeahnte Höhen.
Aber man bekäme doch einen Teil davon wieder herein durch die ansonsten anfallenden Heizkosten, die man sich dadurch spart. Ich meine, angesichts des Wetters heute...
In specifications, Murphy's Law supersedes Ohm's.
BlackJack

@lackschuh: Wie man das Beispiel am besten löst, hängt davon ab wie und was die beiden Threads eigentlich miteinander kommunizieren sollen. Ich sehe da denn Sinn von dem Flag nicht, beziehungsweise nicht wie man das mit vertretbarem Aufwand threadsicher hinbekommt ohne das der Thread der die Emails dann verarbeitet, den Test ob neue E-Mails vorhanden sind, nicht zumindest implizit noch man selber machen muss.
Sirius3
User
Beiträge: 18272
Registriert: Sonntag 21. Oktober 2012, 17:20

@lackschuh: je nach Anwendungsfall bekommst Du bei Deinem Ansatz Probleme, wenn mehr als eine Mail kommt. Wie läuft die Verarbeitung der Mails, wie wird der Inhalt von einem Thread zum anderen übertragen? Queues sind eine Möglichkeit, das sauber abzubilden.
jerch
User
Beiträge: 1669
Registriert: Mittwoch 4. März 2009, 14:19

@lackschuh:
Die Sinnhaftigkeit Deines Beispiels mal ausser Acht lassend hier das Beispiel ohne globale Variable und in threadsafe:

Code: Alles auswählen

# Weg damit, globals sind vorallem mit Threads Ausgeburten der Hölle!
# status = 0

class EmailThread(threading.Thread):
    
    def __init__(self, status):
        threading.Thread.__init__(self)
        self.status = status
        
    def run(self):
        #global status
        while True:
		    #mach was
            if habe_mail == 1: # status wird auf 1 gesetzt
                self.status.set()
				
def main():
    #global status
    # anstelle der globalen Variable nehmen wir eine threadsichere boolsche Variable.
    status = threading.Event()
    while True:
        if not status.is_set():
            pass # mach nichts
            # vllt. dem Teil ein sleep gönnen ;)
        #elif status = 1:
        # nix elif hier, da eh nur 1|0 unterschieden wird
        else:
            ...
        # Aufruf weiterer Funktionen
    ...
    # iwie fehlt noch der Aufruf des Mailthreads (am besten vor dem while, sonst wird das nie erreicht),
    # da kommt das Flag mit rein:
    emailthread = EmailThread(status)
    # und hier rennt er los ...
    emailthread.start()
BlackJack

@jerch: Ob das wirklich threadsafe (genug) ist kommt aber ganz darauf an was dieses Flag bedeutet und wer das wieder löscht.
jerch
User
Beiträge: 1669
Registriert: Mittwoch 4. März 2009, 14:19

BlackJack hat geschrieben:@jerch: Ob das wirklich threadsafe (genug) ist kommt aber ganz darauf an was dieses Flag bedeutet und wer das wieder löscht.
Inwiefern könnte das Flag hier nicht threadsafe sein?
Antworten