Globale Namen definieren ???

Code-Stücke können hier veröffentlicht werden.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

@me: Dein Beispiel ist wirklich gelungen! :-)

(Hätte man ein Wiki, sollte man das da rein packen :mrgreen: )
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
Zappelmann
User
Beiträge: 27
Registriert: Freitag 23. Mai 2014, 11:01

nein bisher kannte ich die Seite nicht aber ich werde mich da mal durchwühlen
also das Beispiel ok hab gerafft das es dabei nicht um die globalen Variablen geht aber wenn ich das richtig verstanden habe soll ich Module bzw. Funktionen auslagern in andere Dateien und diese dann gezielt im Programmablauf einbinden ?

ist das richtig ? bzw ist es in python üblich das man mehrere Dateien für ein Programm in der Größe erstellt ? ich mein im grunde genommen ist es ja ein kleines Script.

ich werde dann mal mich diese Woche mit der Seite beschäftigen.

danke für den Tipp

MFG

Zappelmann
BlackJack

@Zappelmann: Module sind in Python Dateien. Beziehunsgweise umgekehrt: Was in einem Modulobjekt steckt, wird normalerweise durch eine Python-Quelltextdatei definiert.

Es geht hier jetzt erst einmal nur um Funktionen. Der bereits vorhandene Code sollte sich damit vereinfachen lassen in dem man nicht sehr ähnlichen Quelltext immer wieder hinschreibt, sondern Funktionen schreibt die die Unterschiede als Argumente übergeben bekommen.
Zappelmann
User
Beiträge: 27
Registriert: Freitag 23. Mai 2014, 11:01

So nachdem ich mir einige Grundlagen Tutorials reingezogen habe, ich hab genau das gefunden was ich gesucht hatte.
Das hättet ihr aber auch direkt schreiben können das es so einfach ist ^^. Aber gut ich hab Euch verstanden das mir Grundlagen fehlen und ich diese für eine sinnvolle und sauber Programmierung unerlässlich sind. Jedoch hab ich das Script um 50% einkürzen können. Ich weis das ist jetzt noch immer nicht nach Euren Vorstellungen nach guten sauberen Code aber gebt mir noch ein wenig Zeit oder auch ein paar Hinweise wo man es dann noch weiter reduzieren kann. Auf manche Sachen kann ich bisher nicht versichten wie z.B. die Servo Stellungen und die Messungen da diese alle unterschiedlich sind und auch entsprechend benötigt werden. Ich bin mir sicher das Ihr der Meinung seid das es noch einfacher zu schreiben ist. So hier nochmal der bisher überarbeitete Code.


wie alles anfing: https://www.youtube.com/watch?v=oAjxtVcyods
langsam wird er autonom: https://www.youtube.com/watch?v=hN7qRw3E0Gk

Weitere Videos sind in Bearbeitung und werden in Kürze folgen.

Ich bin natürlich weiterhin für konstruktive Kritik offen.


Code: Alles auswählen

#!/usr/bin/python

from time import sleep
import time
import RPi.GPIO as GPIO
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BOARD)
GPIO.setup(19,GPIO.OUT)
GPIO.setup(7,GPIO.OUT)
GPIO.setup(22,GPIO.OUT)
GPIO.setup(11,GPIO.OUT)
GPIO.setup(26,GPIO.OUT)
GPIO.setup(12,GPIO.OUT)
GPIO.setup(16,GPIO.IN)

print "Ultraschallmessung mit HC-SR04"

#A routine to control a pair of pins

def ControlAPairOfPins(FirstPin,FirstState,SecondPin,SecondState):
  if FirstState == "1":
    GPIO.output(int(FirstPin),True)
  else:
    GPIO.output(int(FirstPin),False)
  if SecondState == "1":
    GPIO.output(int(SecondPin),True)
  else:
    GPIO.output(int(SecondPin),False)
  return

def Stop():
    ControlAPairOfPins("19","0","7","0")
    ControlAPairOfPins("22","0","11","0")

def Stop_anhalten_permanent():
    ControlAPairOfPins("19","0","7","0")
    ControlAPairOfPins("22","0","11","0")

def Vorwaerts_fahren():
    ControlAPairOfPins("19","1","7","0")
    ControlAPairOfPins("22","1","11","1")
	
def Geradeaus_vorwaerts_start():
    ControlAPairOfPins("19","1","7","0")
    ControlAPairOfPins("22","1","11","1")
	
def Links_fahren():
    ControlAPairOfPins("19","1","7","0")
    ControlAPairOfPins("22","0","11","1")
    time.sleep(1.5)
	
def Rechts_fahren():
    ControlAPairOfPins("19","1","7","1")
    ControlAPairOfPins("22","1","11","1")
    time.sleep(1.5)

def Rueckwaerts_fahren():
    ControlAPairOfPins("19","1","7","1")
    ControlAPairOfPins("22","0","11","1")
    time.sleep(1.0)

def Rueckwaerts_fahren_l():
    ControlAPairOfPins("19","1","7","1")
    ControlAPairOfPins("22","0","11","1")
    time.sleep(0.5)

def Rueckwaerts_fahren_r():
    ControlAPairOfPins("19","1","7","1")
    ControlAPairOfPins("22","0","11","1")
    time.sleep(0.5)
		
def Servo_permanent_vorn():
    p = GPIO.PWM(26,50)
    p.start(5.5)
    p.ChangeDutyCycle(5.5)
    time.sleep(True)
    p.stop(5.5)

def Servo_permanent_links():
    p = GPIO.PWM(26,50)
    p.start(5.5)
    p.ChangeDutyCycle(8.5)
    time.sleep(0.2)
    p.stop(8.5)

def Servo_permanent_rechts():
    p = GPIO.PWM(26,50)
    p.start(8.5)
    p.ChangeDutyCycle(3.5)
    time.sleep(0.2)
    p.stop(3.5)

def Servo_permanent_mitte():
    p = GPIO.PWM(26,50)
    p.start(3.5)
    p.ChangeDutyCycle(5.5)
    time.sleep(0.2)
    p.stop(5.5)

def Servo_anfang_mitte():
    p = GPIO.PWM(26,50)
    p.start(5.5)
    p.ChangeDutyCycle(5.5)
    time.sleep(0.1)
    p.stop(5.5)

def Servo_links():
    p = GPIO.PWM(26,50)
    p.start(5.5)
    p.ChangeDutyCycle(10.5)
    time.sleep(0.3)
    p.stop(10.5)

def Servo_rechts():
    p = GPIO.PWM(26,50)
    p.start(10.5)
    p.ChangeDutyCycle(1)
    time.sleep(0.3)
    p.stop(1)

def Servo_mitte():
    p = GPIO.PWM(26,50)
    p.start(1)
    p.ChangeDutyCycle(5.5)
    time.sleep(0.2)
    p.stop(5.5)

def Messung_permanent_vorn():
    GPIO.output(12, False)
    time.sleep(0.1)
    GPIO.output(12, True)
    time.sleep(0.00001)
    start = time.time()
    GPIO.output(12, False)
    while GPIO.input(16)==0:
        pass
    start = time.time()
    while GPIO.input(16)==1:
        pass
    stop = time.time()
    elapsed = stop-start
    global dist_vorn_perma
    dist_vorn_perma = elapsed * 17500
    print "Abstand_vorn: %.1f cm" % dist_vorn_perma

def Messung_permanent_links():
    GPIO.output(12, False)
    time.sleep(0.1)
    GPIO.output(12, True)
    time.sleep(0.00001)
    start = time.time()
    GPIO.output(12, False)
    while GPIO.input(16)==0:
        pass
    start = time.time()
    while GPIO.input(16)==1:
        pass
    stop = time.time()
    elapsed = stop-start
    global dist_links_perma
    dist_links_perma = elapsed * 17000
    print "Abstand_links: %.1f cm" % dist_links_perma

def Messung_permanent_rechts():
    GPIO.output(12, False)
    time.sleep(0.1)
    GPIO.output(12, True)
    time.sleep(0.00001)
    start = time.time()
    GPIO.output(12, False)
    while GPIO.input(16)==0:
        pass
    start = time.time()
    while GPIO.input(16)==1:
        pass
    stop = time.time()
    elapsed = stop-start
    global dist_rechts_perma
    dist_rechts_perma = elapsed * 17000
    print "Abstand_rechts: %.1f cm" % dist_rechts_perma

def Messung_distance_vorn():
    GPIO.output(12, False)
    time.sleep(0.5)
    GPIO.output(12, True)
    time.sleep(0.00001)
    start = time.time()
    GPIO.output(12, False)
    while GPIO.input(16)==0:
        pass
    start = time.time()
    while GPIO.input(16)==1:
        pass
    stop = time.time()
    elapsed = stop-start
    global distance
    distance = elapsed * 17500
    print "Abstand_vorn: %.1f cm" % distance

def Messung_dist_links():
    GPIO.output(12, False)
    time.sleep(1)
    GPIO.output(12, True)
    time.sleep(0.00001)
    start = time.time()
    GPIO.output(12, False)
    while GPIO.input(16)==0:
        pass
    start = time.time()
    while GPIO.input(16)==1:
        pass
    stop = time.time()
    elapsed = stop-start
    global dist_links
    dist_links = elapsed * 17000
    print "Abstand_links: %.1f cm" % dist_links

def Messung_dist_rechts():
    GPIO.output(12, False)
    time.sleep(1)
    GPIO.output(12, True)
    time.sleep(0.00001)
    start = time.time()
    GPIO.output(12, False)
    while GPIO.input(16)==0:
        pass
    start = time.time()
    while GPIO.input(16)==1:
        pass
    stop = time.time()
    elapsed = stop-start
    global dist_rechts              #Das es so einfach ist hätte man aber auch schreiben können!^^
    dist_rechts = elapsed * 17000
    print "Abstand_rechts: %.1f cm" % dist_rechts

	
while True:
    Servo_anfang_mitte()
    Vorwaerts_fahren()
    Messung_permanent_vorn()
    if dist_vorn_perma < 25:
        Stop_anhalten_permanent()
        print "STOP_VORN"
        Rueckwaerts_fahren()
        Stop()
        Servo_links()
        Messung_dist_links()
        Servo_rechts()
        Messung_dist_rechts()
        Servo_permanent_mitte()
        if dist_links > dist_rechts:
            Rueckwaerts_fahren_l()
            Links_fahren()
        else:
            Rueckwaerts_fahren_r()
            Rechts_fahren()
    else:
        Geradeaus_vorwaerts_start()
    Servo_permanent_links()
    Messung_permanent_links()
    if dist_links_perma < 12:
        Stop_anhalten_permanent()
        print "STOP_LINKS"
        Rueckwaerts_fahren()
        Stop()
        Servo_rechts()
        Messung_dist_rechts()        
        Servo_links()
        Messung_dist_links()
        Servo_permanent_mitte()
        if dist_rechts > dist_links:
            Rueckwaerts_fahren_l()
            Links_fahren()
        else:
            Rueckwaerts_fahren_r()
            Rechts_fahren()
    else:
        Geradeaus_vorwaerts_start()
    Servo_permanent_rechts()
    Messung_permanent_rechts()
    if dist_rechts_perma < 12:
        Stop_anhalten_permanent()
        print "STOP_RECHTS"
        Rueckwaerts_fahren()
        Stop()
        Servo_links()		
        Messung_dist_links()
        Servo_rechts()
        Messung_dist_rechts()
        Servo_permanent_mitte()
        if dist_links > dist_rechts:
            Rueckwaerts_fahren_l()
            Links_fahren()
        else:
            Rueckwaerts_fahren_r()
            Rechts_fahren()
    else:
        Geradeaus_vorwaerts_start()
MFG

Zappelmann
Zuletzt geändert von Zappelmann am Montag 26. Mai 2014, 18:35, insgesamt 1-mal geändert.
Zappelmann
User
Beiträge: 27
Registriert: Freitag 23. Mai 2014, 11:01

Ach ja da fällt mit gerade etwas ein was mich die ganzen Tage schon beschäftigt hat. Ich weis das man ein GPIO als Input definieren kann. Ich würde gern 2 Taster einsetzen. Einem zum starten der Software und einem zum stoppen der Software. Vielleicht könnt Ihr mir dazu ein Hinweis geben, wo man sowas am besten einfügt.
Im Grunde genommen möchte ich damit erreichen das der beim druck auf einem Taster das Programm an jeder Stelle sofort anhält und sämtliche GPIO Aktivitäten einstellt. Und beim Starten das das Programm natürlich von vorn abläuft.

Ich hoffe das Ihr mir da ein Tipp geben könnt.

In der Zwischenzeit werde ich weiter die Tutorialseiten wälzen um mein Wissen zu vertiefen.

MFG

Zappelmann
Sirius3
User
Beiträge: 17749
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: 6740
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: 1484
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.
Antworten