Seite 1 von 1
Zählen lassen
Verfasst: Freitag 5. Dezember 2014, 11:32
von lackschuh
Hallo
Ein hier häufig gelesener Satz lautet: "Nicht selber zählen, zählen lassen"
Wie zähle ich zB die Anzahl einer aufgerufenen Funktion ohne globale Variablen?
Hier habe ich es so gelöst:
Code: Alles auswählen
def counter(func):
@wraps(func)
def tmp(*args, **kwargs):
tmp.count += 1
return func(*args, **kwargs
Ein anderes Beispiel ist dieser
Thread:
Code: Alles auswählen
def motion_detected(channel):
print('Motion detected Nr.: ')
def main():
GPIO.add_event_detect(PIR_PIN, GPIO.RISING, callback=motion_detected)
# print Anzahl Aufrufe von motion_detected()
if __name__ == '__main__':
main()
Re: Zählen lassen
Verfasst: Freitag 5. Dezember 2014, 14:56
von lackschuh
Leider kann ich nicht mehr editieren:
Ich meine, wie kann so etwas vermieden werden im Kontext zum obigen Beispiel:
Code: Alles auswählen
count = 0
def motion_detected(channel):
global count
count = count + 1
print(count)
Re: Zählen lassen
Verfasst: Freitag 5. Dezember 2014, 15:24
von BlackJack
@lackschuh: Na da würde doch der Dekorator funktionieren‽
Wenn man nicht *einen* Zähler fest an die Funktion binden möchte, kann man so etwas machen:
Code: Alles auswählen
def motion_detected(channel):
print('Motion detected Nr.: ')
class CallCounter(object):
def __init__(self, function):
self.function = function
self.count = 0
def __call__(self, *args, **kwargs):
self.count += 1
self.function(*args, **kwargs)
def main():
counted_motion_detected = CallCounter(motion_detected)
GPIO.add_event_detect(PIR_PIN, GPIO.RISING, callback=counted_motion_detected)
print(counted_motion_detected.count)
So könnte man dann auch die gleiche Funktion für unabhängige Bewegungssensoren verwenden.
Re: Zählen lassen
Verfasst: Freitag 5. Dezember 2014, 15:32
von lackschuh
@BlackJack
Danke, so könnte ich auf den Dekorator verzichten (so wie du es im anderen
Thread geschrieben hast) und die Klasse noch mit anderen Attributen vollstopfen(?)
Re: Zählen lassen
Verfasst: Freitag 5. Dezember 2014, 16:05
von BlackJack
@lackschuh: Die Formulierung klingt ja nicht gut.

Man könnte statt solcher generischen Sachen auch eine Klasse schreiben die einen Bewegungsensor modelliert und die dann auch gleich Thread-sicher machen. Also zum Beispiel so etwas in dieser Richtung:
Code: Alles auswählen
class MotionDetector(object):
def __init__(self, pin, callback=None):
self.pin = pin
self.callback = callback
self.lock = threading.Lock()
self.count = 0
GPIO.add_event_detect(
self.pin, GPIO.RISING, callback=self.motion_detected
)
def motion_detected(self, channel):
with self.lock:
self.count += 1
if self.callback:
self.callback(channel)
def get_and_reset_count(self):
with self.lock :
result = self.count
self.count = 0
return result
def main():
motion_detector = MotionDetector(PIR_PIN)
while True:
time.sleep(1)
print(motion_detector.get_and_reset_count())