Parameter in dynamischen Funktionsaufruf übergeben

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Benutzeravatar
Damaskus
Administrator
Beiträge: 1010
Registriert: Sonntag 6. März 2005, 20:08
Wohnort: Schwabenländle

Hallo Zusammen,

ich suche nach einer Möglichkeit bei einem Callback eines Tinkerforge Bricks die UID des Bricks zu übergeben.
Da die Bricks über ein Interface konfiguriert werden können, vorallem die für den Brick zu verwendende Brick UID muss ich den Callback aufruf dynamisch machen.
Den Aufruf etc. bekomme ich auch Problemlos hin, allerdings fällt mir im Moment nicht die richtige Lösung ein um innerhalb der Klasse von __getattr__ die richtige "brickuid" nach cb_moisture bei jedem Aufruf des Callbacks weiter zu reichen.

Anbei ein Bsp. was es evtl. besser beschreibt:

Code: Alles auswählen

# !/usr/bin/env python
# -*- coding: utf-8 -*-  

HOST = "192.168.178.36"
PORT = 4223
UID = ["kwJ", "kyc", "hjk", 'Fgt']

from tinkerforge.ip_connection import IPConnection
from tinkerforge.bricklet_moisture import Moisture
import string


class MyClass(object):
    def __init__(self):
        pass

    def cb_moisture(moisture):
        # brickuid = ??? <<< Hier wird die BrickUID benoetigt
        print('Moisture Value: ' + str(moisture))

    def __getattr__(self, name):
        if name.startswith('cb_moisture_'):
            brickuid = name[12:]  # <<< hier ist die BrickUID
            return self.cb_moisture

cb = MyClass()

if __name__ == "__main__":
    ipcon = IPConnection()
    ipcon.connect(HOST, PORT)

    for u in UID:
        m = Moisture(u, ipcon)
        m.set_moisture_callback_period(1000)
        methodToCall = getattr(cb, 'cb_moisture_' + string.lower(u))
        m.register_callback(m.CALLBACK_MOISTURE, methodToCall)

    raw_input('Press key to exit\n')
    ipcon.disconnect()
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Hallo.

Das kannst du einfach mit ``functools-partial`` machen.
Das Leben ist wie ein Tennisball.
BlackJack

@Damaskus: Das mit `__getattr__` sieht extrem kompliziert aus. Du missbrauchst nicht wirklich vorhandene Methodennamen um Argumente zu übergeben wobei die auch gar nicht tatsächlich in den Quelltext geschrieben werden, sondern generiert werden. Warum‽
Benutzeravatar
Damaskus
Administrator
Beiträge: 1010
Registriert: Sonntag 6. März 2005, 20:08
Wohnort: Schwabenländle

@BlackJack: Das Bsp. war ziemlich reduziert. Es geht mir darum die Messwerte von ca. 40 Bricklets in einer DB zu speichern und über die jeweilige Id einem Sensor zu zu weisen. Und da die Konfiguration der Sensoren sich immer wieder ändert dachte ich, ich übergebe die ID im Funktionsname des Callbacks, werte den Aufruf aus, schneide die UID aus und mappe den Aufruf an eine "Universal" Funktions. Und muss nicht x-mal den Callback schreiben...

Code: Alles auswählen

def cb_moisture_xyz(moisture):
    uid = 'XYZ'
    print('Moisture Value: ' + str(moisture) + '     UID: ' + uid)

Wenn ich aber von Anfang an, an "functools" gedacht hätte, wäre so ein Krampf mit __getattr__ nie heraus gekommen.
Lösung mit functools:

Code: Alles auswählen

# !/usr/bin/env python
# -*- coding: utf-8 -*-  

HOST = "192.168.178.36"
PORT = 4223
UID = ["kwJ", "kyc"]

from tinkerforge.ip_connection import IPConnection
from tinkerforge.bricklet_moisture import Moisture
import string
import functools


def temp_cb_moisture(moisture, uid):
    print('Moisture Value: ' + str(moisture) + '     UID: ' + uid)

if __name__ == "__main__":
    ipcon = IPConnection()
    ipcon.connect(HOST, PORT)

    for u in UID:
        m = Moisture(u, ipcon)
        m.set_moisture_callback_period(1000)
        cb_moisture = functools.partial(temp_cb_moisture, uid=u)
        m.register_callback(m.CALLBACK_MOISTURE, cb_moisture)

    raw_input('Press key to exit\n')
    ipcon.disconnect()
@EyDu: Danke!
Antworten