Dynamisch Methoden einer Klasse referenzieren

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
pommespaula
User
Beiträge: 5
Registriert: Donnerstag 10. Mai 2012, 16:12

Hallo,

schöne Grüße erst einmal an das Forum. Ich bin recht neu in der Python-Programmierung und habe in der nächsten Zeit sicherlich etliche Fragen. Vielen Dank also schon einmal vorweg für alle eure Antworten.

Ich versuche aktuell ein Messprogramm für unser Labor zu schreiben. Jedes Messgerät soll als Objekt angelegt werden. Die Methoden des Objekts repräsentieren dann Kanäle des Messgeräts.

Ich möchte mein Vorhaben stark vereinfacht anhand eines Voltmeters erklären. Das Voltmeter besitzt z.B zwei Kanäle um Spannungen zu messen. Je nach Experiment können dieses Spannungen aber eine andere Bedeutung haben, mal repräsentieren sie eine Temperatur oder ein anderes mal die Stärke eines Magnetfeldes. Der Benutzer soll nun in der Lange sein diesem Kanal einen physikalisch sinnvollen Namen zu geben und darüber zugreifen zu können.

Was ich nun wissen möchte ist, wie ich dieses am geschicktesten realisiere. Hier mal was ich mir gedacht habe und was auch funktioniert.

Code: Alles auswählen

class voltmeter(object):
        def __init__(self, name1, name2):
                self.__channels = {name1 : self.channel01,
                                   name2 : self.channel02}
       
        def readchannel(self, name):
                channelreference = self.__channels[name]
                return channelreference()
        
        def channel01(self):
                return "Spannungswert 01"
 
        def channel02(self):
                return "Spannungswert 02"

               
FooVolt = voltmeter('magnetfeld', 'temperatur')
print FooVolt.readchannel('magnetfeld')
print FooVolt.readchannel('temperatur')

Code: Alles auswählen

Ausgabe:
# Spannungswert 01
# Spannungswert 02
Da dieses einen sehr wichtiger Teil des Programms ausmacht, möchte ich gerne vorweg sicherstellen den richtigen Weg zu gehen. Allerdings bin ich mir nicht sicher ob dieses der richtige Weg ist um Methoden zu referenzieren.
Ich würde mich sehr freuen, wenn mir jemand sagen könnte ob ich die Sache richtig oder falsch angehe. Lasst mich aber auch bitte wissen, wenn ihr meine Frage nicht versteht.

Vielen Dank schon einmal für alle Antworten.
BlackJack

@pommespaula: Das kann man so machen, aber ich würde die Methoden `channel01()` und `channel02()` mal in Frage stellen. Die beiden Kanäle werden ja nicht komplett unterschiedlich angesprochen werden, so das eine Methode bei der der Kanal als Argument übergeben wird, viel wahrscheinlicher ist. Wenn man anfängt Namen durch zu nummerieren stimmt in 99% der Fälle etwas am Entwurf nicht.

Zur Form: Schau mal in den PEP 8 -- Style Guide for Python Code. Das müsste also `Voltmeter`, `read_channel`, und `foo_volt` heissen. Ausserdem Einrücken um vier Leerzeichen pro Ebene.

Und der doppelte Unterstrich bei `__channels` sollte zu einem werden.
pommespaula
User
Beiträge: 5
Registriert: Donnerstag 10. Mai 2012, 16:12

Hey Danke für deine Rückmeldung und deinen Link für "guten" Code.

Das Beispiel war sehr vereinfacht dargestellt und in dem Falle sicherlich wenig ideal. Im Realfall besitzt aber jeder Messaufbau viele Messgeräte mit sehr unterschiedlichen Funktionen. Ein Voltmeter z.B. besitzt z.B. mehre identische Spannungseingänge aber auch Funktionen wie Messbereich, Rauschfilterung, Integrationszeit, etc. Ein anderes Messgerät überwacht die Temperatur des Experiments. Über all diese sehr unterschiedlichen Funktionen von verschiedenen Messgeräten soll das Channel-Konstrukt als Abstraktionsebene gelegt werden. Wodurch ein einheitlicher Zugriff erlaubt wird.

* Messgerät Treiber -> Greift auf die Hardware des Messgeräts zu.
* Channel Interface -> Verknüpft die Funktionen der Messgeräte mit den "Channels" und erlaubt einen einfachen Zugriff darauf.
* Messprogramm -> Kann Channels auslesen und steuern.
BlackJack

@pommespaula: Das ändert alles nichts daran, dass eine Methode pro Kanal wobei die Kanäle durchnummeriert sind, ein schlechter Entwurf ist. Dafür braucht man nur *eine* Methode, welche die Kanalnummer als Argument übergeben bekommt. Dann ist die Kanalnummer ein Wert, den man im Programm verarbeiten kann, vom Benutzer eingeben lassen kann, in Dateien speichern kann, und so weiter.
pommespaula
User
Beiträge: 5
Registriert: Donnerstag 10. Mai 2012, 16:12

@BlackJack Mh ich versuche gerade zu verstehen was du mir mitteilen möchtest. Die Kanäle unterscheiden sich ja in ihrer Funktionsweise und in der Art und Weise wie sie ausgelesen bzw. gesetzt werden fundamental voneinander. Ich wüsste gerade nicht wie ich ohne entsprechende Referenzen mein Vorhaben umsetzen sollte.
BlackJack

@pommespaula: An einem Gerät unterscheidet sich das bei den verschiedenen Kanälen so grundsätzlich? Ich habe Schwierigkeiten mir das vorzustellen. Wenn das so unterschiedlich ist, wie kann man es dann auf gleichartige Kanäle umsetzen? Wenn die nicht alle gleichartig verwendbar sind, macht es ja keinen Sinn sie zu haben. Das klingt jetzt irgendwie so als wenn konkrete Methoden auf namenlose Kanäle abstrahiert werden, um sie im nächsten Schritt dann wieder mit konkreten Namen zu versehen‽
pommespaula
User
Beiträge: 5
Registriert: Donnerstag 10. Mai 2012, 16:12

Gemeinsam haben alle Channels aller Messgeräte immer nur, dass sie entweder einen Wert lesen oder senden. Es muss also zwischen Lese- und Schreibchannels unterschieden werden und mehr muss der Benutzer nicht wissen. Wie jetzt die genaue Kommunikation mit den Messgeräten über das GPIB Bus System geschieht und welche unterschiedlichen Befehlsätze gesendet werden soll über das Channelkonzept ausgebledendet werden. Den Benutzer kümmert es nichteinmal, dass die Channels zu unterschiedlichen Messgeräten gehören. Das Channel Konzept ist daher noch etwas allgemeiner gefasst als es im Beispiel der Fall ist.

Ich denke aber nochmal genau drüber nach, ob es Sinn es irgendwie mehr Sinn macht die Channels mittels Abfragen zu realisieren anstatt sie zu als Methoden zu realisieren. Vielen Danke für deine ganzen Anregungen, werde es im Hinterkopf behalten.
BlackJack

@pommespaula: Vielleicht macht es auch mehr Sinn die Kanäle als Klassen zu modellieren. Und die Geräte als Container-Objekte auf deren Elemente man über die Kanalnummer oder einen symbolischen Namen zugreifen kann. So dass der Code dann zum Beispiel so aussehen kann:

Code: Alles auswählen

    device = Device()
    
    device[0].send(42)
    value = device[1].receive()

    for channel in device:
        print channel.number, channel.name, channel.direction
    # Prints '0 command OUT' and '1 voltage IN'.

    device['command'].send(42)
    value = device['voltage'].receive()
pommespaula
User
Beiträge: 5
Registriert: Donnerstag 10. Mai 2012, 16:12

Ich werde die nächsten Tage/Wochen mal anfange Treiber für zwei Geräte zu schreiben. Werde mir danach genau überlegen wie ich das Channel-Interface am besten darüber legen und ggf. nochmal auf deine Vorschläge zurück kommen. Vielen Dank schon einmal für deine vielen Anregungen.
Antworten