Wert aus Dictionary als neuer Variablennamen als Schleife

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
StefanB
User
Beiträge: 7
Registriert: Dienstag 3. September 2013, 10:19

Hallo liebes Forum !

Aller Anfang ist schwer und genau gesshalb bin ich hier! Habe jetzt schon eine gefühlte Ewigkeit mit dem Problem gekämpft, aber es will sich einfach kein brauchbares Ergebnis finden lassen. Vielleicht ist ja hier ein hilfsbereiter User dabei, der mir ein bisschen unter die Arme greifen kann!

Beschreibung des Projekts: Modellbahnsteuerung mittels RaspberryPi
Details: Am Pi sind mehrere "Module" via I2C angeschlossen. Die Module werden über Adressen angesprochen.

Konkretes "Problem": Es soll beim Programmstart eine Art "Autokonfiguration" erfolgen, die den Bus nach gültigen "Modulen" absucht. Funktioniert auch prima soweit...
Die gefundenen "Onlinemodule" stehen jetzt in einer Liste ("onlinemodule").

Wie kann ich jetzt für jedes Modul eine neue Instanz der Klasse "Modul" automatisch anlegen "lassen"? Er soll praktisch den "item-wert" des Diconary´s
als Teil des Instanznamen "berechnen" und beim Erstellen den "Wert" der Liste "onlinemodule" als "addr" übergeben ?

Code:

Code: Alles auswählen

### Modulklasse ###

from conf.hardware import *

class Modul():
    
    def __init__(self, addr):
        self.adresse = addr
        
                
    def test(self):
        try:
            t = i2c.read_byte_data(self.adresse, 0x00) 
            if t >= 0: 
                print "Modul", self.adresse, "Online"
        except IOError:
            print "Modul", self.adresse, "Offline"
    
    def wei(self):
        i2c.write_byte_data(self.adresse, 0x06, 0)
        i2c.write_byte_data(self.adresse, 0x07, 0)
    
    def mel(self):
        i2c.write_byte_data(self.adresse, 0x06, 1)
        i2c.write_byte_data(self.adresse, 0x06, 1)
        
    
            
def auto():
    module = {0x20 : 0,
              0x21 : 1,
              0x22 : 2,
              0x23 : 3,
              0x24 : 4,
              0x25 : 5,
              0x26 : 6,
              0x27 : 7,
              0x28 : 8,
              0x30 : 9}
    onlinemodule = []    
    for addr in module.keys():
        try:
            i2c.read_byte_data(addr, 0x00)
            onlinemodule += [hex(addr)]
        except IOError:
            continue
    
    print onlinemodule
Ergebnis des Printbefehls: ['0x20', '0x21', '0x22']
Er hat also 3 Module gefunden, und dessen "Busadressen" in die Liste geschrieben.

Ich hoffe das das jetzt nicht zu "verwirrend" beschrieben ist…
Bedanke mich jedenfalls schon jetzt für Eure Hilfe!
Stefan
Benutzeravatar
/me
User
Beiträge: 3556
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

StefanB hat geschrieben:

Code: Alles auswählen

            onlinemodule += [hex(addr)]
Das soll wohl eher wie folgt aussehen:

Code: Alles auswählen

            onlinemodule.append(Modul(hex(addr)))
BlackJack

@StefanB: Du willst keine Namen berechnen und schon gar nicht durchnummerierte Namen. Dafür gibt es Datenstrukturen wie Listen und Wörterbücher.

Ich bin mir auch nicht ganz sicher ob die `i2c`-Funktionen tatsächlich *Zeichenketten* mit Hexdarstellungen von Adresswerten als erstes Argument haben wollen. Das sieht mir sehr falsch aus.
StefanB
User
Beiträge: 7
Registriert: Dienstag 3. September 2013, 10:19

ok… also wenn ich das Dictionary so erstelle:

Code: Alles auswählen

module = {0x20 : "Modul0",
              0x21 : "Modul1",
              0x22 : "Modul2",
              0x23 : "Modul3",
              0x24 : "Modul4",
              0x25 : "Modul5",
              0x26 : "Modul6",
              0x27 : "Modul7",
              0x28 : "Modul8",
              0x30 : "Modul9"}
muss ich ja wirklich den Namen nicht berechnen.
Und die Liste mit den Module die "Online" sind kann ich mir ja theoretisch auch sparen, die interessiert mich ja später nicht mehr wirklich…

Aber wie kann ich jetzt in der "for"- Schleife mit den Werten des Dicionary´s arbeiten?

Mein Verständnis bis jetzt ist ja: im "Hauptprogramm" (hier moba.py) erstelle ich eine neue Instanz der Klasse "Modul" mit dem Aufruf "Modul1 = Modul(0x20)". Ab jetzt kann ich die vordefinierten Funktionen der Klasse "Modul" verwenden.
Wie kann ich jetzt dem Ding sagen, dass er in der "for"-Schleife die Instanzen "starten" soll ? Oder bin ich da auf dem völlig falschen weg…

Meine Versuche in Richtung :

Code: Alles auswählen

for addr in module.keys():
        try:
            i2c.read_byte_data(addr, 0x00)
            "%s" % (module[addr] = Modul(module[addr])
            onlinemodule += [hex(addr)]
        except IOError:
            continue
schlugen ja gänzlich fehl…
BlackJack

@StefanB: Ich würde sagen völlig falscher Weg. Du bringst anscheinend zumindest mal Zeichenkettendarstellungen von Werten und den Werten selber völlig durcheinander.

Nochmal: Du willst keine durchnummerierten Namen. Nicht in Wörterbüchern und schon gar nicht in Python direkt. Und dynamisch erzeugen willst Du solche Namen überhaupt nicht. Du willst nicht heisst hier Du sollst so etwas nicht wollen. Das ist Unsinn und macht alles nur unnötig kompliziert.

Was Du wahrscheinlich haben möchtest ist so etwas:

Code: Alles auswählen

def auto_discover():
    modules = dict()
    for i, address in enumerate(
        [0x20, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x30]
    ):
        try:
            module = Modul(address)
        except IOError:
            pass
        else:
            modules[i] = module
    return modules
Das gibt ein Wörterbuch zurück das Zahlen von 0 bis 9 auf Module abbildet, sofern das jeweilige Modul erstellt werden konnte.
StefanB
User
Beiträge: 7
Registriert: Dienstag 3. September 2013, 10:19

so, ich hab´s !

Code: Alles auswählen

for addr in module.keys():
        try:
            i2c.read_byte_data(addr, 0x00)
            tempModul = Modul([hex(addr)])
            print tempModul            
        except IOError:
            continue
ergebnis des print-befehls:

Code: Alles auswählen

python moba.py 
<lib.module.Modul instance at 0xb6c84fa8>
<lib.module.Modul instance at 0xb6c84f30>
<lib.module.Modul instance at 0xb6c84fa8>
<lib.module.Modul instance at 0xb6c84f30>
...aber da kommt sicher noch mehr! Danke Euch !
Sirius3
User
Beiträge: 17754
Registriert: Sonntag 21. Oktober 2012, 17:20

Welchen Zweck erfüllt überhaupt »onlinemodule«?
Du kannst Module auch in Listen speichern und dann mit Listen arbeiten:

Code: Alles auswählen

def auto():
    module_addrs = [0x20,  0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x30]
    onlinemodules = []    
    for addr in module_addrs:
        try:
            i2c.read_byte_data(addr, 0x00)
            onlinemodules.append(Modul(addr))
        except IOError:
            pass
StefanB
User
Beiträge: 7
Registriert: Dienstag 3. September 2013, 10:19

@Sirius3:

Also die Ausgabe mittels "print onlinemodule" ergibt bei Deinem Vorschlag:

Code: Alles auswählen

python moba.py 
[<lib.module.Modul instance at 0xb6d09058>]
[<lib.module.Modul instance at 0xb6d09058>, <lib.module.Modul instance at 0xb6d03f58>]
[<lib.module.Modul instance at 0xb6d09058>, <lib.module.Modul instance at 0xb6d03f58>, <lib.module.Modul instance at 0xb6d1cc38>]
[<lib.module.Modul instance at 0xb6d09058>, <lib.module.Modul instance at 0xb6d03f58>, <lib.module.Modul instance at 0xb6d1cc38>, <lib.module.Modul instance at 0xb6d1cc60>]
[<lib.module.Modul instance at 0xb6d09058>, <lib.module.Modul instance at 0xb6d03f58>, <lib.module.Modul instance at 0xb6d1cc38>, <lib.module.Modul instance at 0xb6d1cc60>]
[<lib.module.Modul instance at 0xb6d09058>, <lib.module.Modul instance at 0xb6d03f58>, <lib.module.Modul instance at 0xb6d1cc38>, <lib.module.Modul instance at 0xb6d1cc60>]
[<lib.module.Modul instance at 0xb6d09058>, <lib.module.Modul instance at 0xb6d03f58>, <lib.module.Modul instance at 0xb6d1cc38>, <lib.module.Modul instance at 0xb6d1cc60>]
[<lib.module.Modul instance at 0xb6d09058>, <lib.module.Modul instance at 0xb6d03f58>, <lib.module.Modul instance at 0xb6d1cc38>, <lib.module.Modul instance at 0xb6d1cc60>]
[<lib.module.Modul instance at 0xb6d09058>, <lib.module.Modul instance at 0xb6d03f58>, <lib.module.Modul instance at 0xb6d1cc38>, <lib.module.Modul instance at 0xb6d1cc60>]
[<lib.module.Modul instance at 0xb6d09058>, <lib.module.Modul instance at 0xb6d03f58>, <lib.module.Modul instance at 0xb6d1cc38>, <lib.module.Modul instance at 0xb6d1cc60>]
Ist das so richtig ?
StefanB
User
Beiträge: 7
Registriert: Dienstag 3. September 2013, 10:19

merke aber gerade dass es so doch noch nicht so ganz richtig ist… er hat zwar (mittlerweile) 4 Instanzen angelegt, aber ich kann sie ja so noch nicht "wirklich" ansprechen.

Der Befehl wäre ja im "Hauptprogramm": Modul1 = Modul(0x20) …würde ich eine Instanz "von Hand" anlegen.

bis jetzt legt er aber 4 Instanzen des "tempModuls" an… Nicht ganz richtig…
BlackJack

@StefanB: Was ist denn daran nicht richtig? Offenbar gibt es ein Modul für die Adresse 0x20. Und das steht in der Liste.
StefanB
User
Beiträge: 7
Registriert: Dienstag 3. September 2013, 10:19

Und wie kann ich jetzt damit "arbeiten" ? Der Aufruf: Modul1.test() z.B. geht nicht !?
StefanB
User
Beiträge: 7
Registriert: Dienstag 3. September 2013, 10:19

ok, habe verstanden… Mit dem Aufruf : Modul(0x20).test() geht´s…

und wie könnte man es jetzt "hinbiegen", dass anstatt dem (0x20) der Dictionary-Eintrag "Modul0" funktioniert ?
BlackJack

@StefanB: Die Funktion gibt eine Liste zurück. Vielleicht möchtest Du mal ein Grundlagentutorial durcharbeiten wo die eingebauten Datentypen wie Listen, Wörterbücher, und so weiter, erklärt werden. In der Python-Dokumentation gibt es ein Tutorial.

Wenn Du statt einer Liste ein Wörterbuch (`dict`) haben möchtest, dazu habe ich eine Funktion gezeigt die ein solches erzeugt. Allerdings nicht mit Zeichenketten wie 'Modul0' als Schlüssel, weil ich darin immer noch keinen Sinn sehe das so kompliziert zu machen.
Antworten