Hallo zusammen
Ich benötige eine Funktion welche einen Takt vorgibt, welcher in anderen Funktionen verwendet wird.
Meine Lösung funktioniert soweit, aber nur mit einer globalen Variablen
Hat jemand eine Idee, wie man das ändern könnte?
def runNext(takt, intervall):
global sekCount
if takt == True:
sekCount = sekCount + 1
if sekCount >= intervall:
sekCount = 0
return True
else:
return False
Gruss
Thomas
Globale Variable umgehen
Mein erster Gedanke: Den Zähler und die Funktion in eine Klasse kippen und um zu verhindern dass von der klasse mehrfach unterschiedliche Objekte erzeugt werden, das Singleton-Entwurfsmuster benutzen.
Um das Singleton-Entwurfsmuster in Python umzusetzen gibt es verschiedene Möglicheiten: https://www.geeksforgeeks.org/singleton ... ete-guide/
Wobei auf der Webseite die erste mögliche Umsetzung ist das ganze auf Modul-Ebene zu verwenden. Also doch keine Klasse, mach einfach ein Modul draus...
Datei taktgeber.py:
Fertig...
In der Nutzung:
Datei mach_was_wichtiges_im_takt.py:
Ungetestet, aber sollte eigentlich laufen denke ich
Um das Singleton-Entwurfsmuster in Python umzusetzen gibt es verschiedene Möglicheiten: https://www.geeksforgeeks.org/singleton ... ete-guide/
Wobei auf der Webseite die erste mögliche Umsetzung ist das ganze auf Modul-Ebene zu verwenden. Also doch keine Klasse, mach einfach ein Modul draus...
Datei taktgeber.py:
Code: Alles auswählen
sekCount = 0
def run_next(takt, intervall):
if takt == True:
sekCount = sekCount + 1
if sekCount >= intervall:
sekCount = 0
return True
else:
return False
In der Nutzung:
Datei mach_was_wichtiges_im_takt.py:
Code: Alles auswählen
from taktgeber import run_next
if run_next(True, 42):
# mache hier irgendwas wichtiges
- __blackjack__
- User
- Beiträge: 13114
- Registriert: Samstag 2. Juni 2018, 10:21
- Wohnort: 127.0.0.1
- Kontaktdaten:
@Hellstern: Namen werden in Python klein_mit_unterstrichen geschrieben. Ausnahmen sind Konstanten (KOMPLETT_GROSS) und Klassen (PascalCase).
Namen sollten auch keine kryptischen Abkürzungen enthalten. SEK ist ja etwas geläufiger, da muss man nicht so lange raten, da ist dann aber nicht gut Deutsch und Englisch in einem Namen zu mischen. Also besser auf eine Sprache festlegen.
Man macht keine Vergleiche mit literalen Wahrheitswerten. Bei dem Vergleich kommt doch nur wieder ein Wahrheitswert bei heraus. Entweder der, den man sowieso schon hatte; dann kann man den auch gleich nehmen. Oder das Gegenteil davon; dafür gibt es ``not``.
Wenn man sich Zustand über Aufrufe hinweg merken will, verwendet man Klassen.
Namen sollten auch keine kryptischen Abkürzungen enthalten. SEK ist ja etwas geläufiger, da muss man nicht so lange raten, da ist dann aber nicht gut Deutsch und Englisch in einem Namen zu mischen. Also besser auf eine Sprache festlegen.
Man macht keine Vergleiche mit literalen Wahrheitswerten. Bei dem Vergleich kommt doch nur wieder ein Wahrheitswert bei heraus. Entweder der, den man sowieso schon hatte; dann kann man den auch gleich nehmen. Oder das Gegenteil davon; dafür gibt es ``not``.
Wenn man sich Zustand über Aufrufe hinweg merken will, verwendet man Klassen.
Code: Alles auswählen
class SWATCounter:
def __init__(self):
self.swat_count = 0
def run_next(self, takt, intervall):
self.swat_count += int(takt)
result = self.swat_count >= intervall
if result:
self.swat_count = 0
return result
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
- DeaD_EyE
- User
- Beiträge: 1021
- Registriert: Sonntag 19. September 2010, 13:45
- Wohnort: Hagen
- Kontaktdaten:
Einfach global zu entfernen, bringt nichts.
Mit einer Klasse.
Könnte so aussehen:
Code ist nicht getestet. Die Namen habe ich mal an die Konventionen angepasst.
Man könnte das auch mit Funktionen erreichen, muss dann aber alle benötigen Argumente immer strikt mit angeben. Man hat auch nicht immer die Kontrolle darüber, was einer Funktion an Argumenten übergeben wird, wenn man z.B. Callbacks nutzt. Die aufrufende Funktion (z.B. von GPIO) bestimmt die Argumente. Bei RPi.GPIO wird bei einem Interrupt die Pin-Nummer der Funktion übergeben. Wenn man dann in diesem Aufruf weitere Argumente benötigt, wird es kompliziert. Da müsste dann man mit Closures (Funktion in Funktion) arbeiten.
Im Allgemeinen sind Klassen einfacher, wenn man sie verstanden hat.
Mit self ist die Instanz gemeint und auf self kann zugegriffen werden. Die Angab
Code: Alles auswählen
sekCount = 0
def run_next(takt, intervall):
if takt == True:
sekCount = sekCount + 1 # <- UnboundLocalError
if sekCount >= intervall:
sekCount = 0
return True
else:
return False
Mit einer Klasse.
Könnte so aussehen:
Code: Alles auswählen
import RPi.GPIO as gpio
class SignalCounter:
def __init__(self, intervall, takt_pin):
self.seek_count = 0
self.intervall = intervall
self.takt_pin = takt_pin
gpio.setup(takt_pin, gpio.IN, pull_up_down=GPIO.PUD_DOWN)
def run_next(self):
"""
polling
https://sourceforge.net/p/raspberry-gpio-python/wiki/Inputs/
"""
if gpio.input(self.takt_pin):
self.seek_count += 1
if self.seek_count >= self.intervall:
self.seek_count = 0
# not bool(0) -> True
# not bool(1) -> False
return not bool(self.seek_count)
if __name__ == __main__:
gpio.setmode(gpio.BCM)
sc = SignalCounter(10, 22)
# wodurch wird run_next aufgerufen?!
while True:
sc.run_next()
time.sleep(0.1)
# intervall von 100 ms, alles was dazwischen
# passiert, geht einfach verloren
Man könnte das auch mit Funktionen erreichen, muss dann aber alle benötigen Argumente immer strikt mit angeben. Man hat auch nicht immer die Kontrolle darüber, was einer Funktion an Argumenten übergeben wird, wenn man z.B. Callbacks nutzt. Die aufrufende Funktion (z.B. von GPIO) bestimmt die Argumente. Bei RPi.GPIO wird bei einem Interrupt die Pin-Nummer der Funktion übergeben. Wenn man dann in diesem Aufruf weitere Argumente benötigt, wird es kompliziert. Da müsste dann man mit Closures (Funktion in Funktion) arbeiten.
Im Allgemeinen sind Klassen einfacher, wenn man sie verstanden hat.
Mit self ist die Instanz gemeint und auf self kann zugegriffen werden. Die Angab
sourceserver.info - sourceserver.info/wiki/ - ausgestorbener Support für HL2-Server
Ah, deswegen haben sie auf der geekforgeeks-Seite im singleton.py nur die Variable shared_variable definiert und keine Funktion. Dann also doch eine Klasse, aber eben verhindern das mehrere unterschiedliche Taktgeber instanziert werden können (siehe oben bei geeforgeeks.org)DeaD_EyE hat geschrieben: ↑Dienstag 24. Januar 2023, 12:15 Einfach global zu entfernen, bringt nichts.
Code: Alles auswählen
sekCount = 0 def run_next(takt, intervall): if takt == True: sekCount = sekCount + 1 # <- UnboundLocalError if sekCount >= intervall: sekCount = 0 return True else: return False
Diesmal was getestetes
takt.py:
Auch wieder mit einer Klasse. Aber in Python ist ja alles eine Klasse, auch die Funktion run_next. Also nutzen wir sie.... Aber ich bin nicht sicher ob ich das so nutzen würde, auch wenn es funktioniert.
takt.py:
Code: Alles auswählen
## takt.py
def run_next(takt, intervall):
if takt == True:
run_next.zaehler = run_next.zaehler + 1
if run_next.zaehler >= intervall:
run_next.zaehler = 0
return True
else:
return False
run_next.zaehler = 0
- DeaD_EyE
- User
- Beiträge: 1021
- Registriert: Sonntag 19. September 2010, 13:45
- Wohnort: Hagen
- Kontaktdaten:
grubenfox hat geschrieben: ↑Dienstag 24. Januar 2023, 13:08Auch wieder mit einer Klasse.Code: Alles auswählen
def run_next(takt, intervall): ...
Die Funktion ist keine Klasse und es erscheint auch nicht auf automagische Weise das Attribut zaehler.
Man könnte unter anderem die Klasse types.SimpleNamespace als Container verwenden und dem Objekt ein Attribut zuweisen.
Geht auch mit ganz normalen Klassen.
Code: Alles auswählen
from types import SimpleNamespace
ns = SimpleNamespace(count=0)
def count_up():
ns.count += 1
for _ in range(10):
count_up()
print(ns.count)
Wenn du noch nicht genau weißt, was Klassen sind, dann müsstest du dich damit erst mal intensivst mit auseinandersetzen.
sourceserver.info - sourceserver.info/wiki/ - ausgestorbener Support für HL2-Server