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())