Zugriff via property und index auf ctypes-array in Klasse;

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
ddpf
User
Beiträge: 21
Registriert: Freitag 22. Februar 2013, 12:13

Ich habe ein ctypes array das aus Kanälen besteht. Jedem Kanal ist ein Element aus dem array zugewiesen (Vereinfachtes Beispiel). Ich habe eine setter-Methode (set_register_channel(self, ch, value)) und eine getter-Methode (get_register_channel(self, ch)). Ich möchte jetzt eine property haben die wie folgt aussieht beim Zugriff:

object.channel_array[x] = y
output = object.channel_array[x]

wobei x ein beliebiger aber begrentzer Integerwert ist um einen Kanal anzusprechen und y ein beliebiger Integerwert. z.B. channel_array[2] = 20 # Schreibe in Kanal 2 (x = 2) den Wert 20 (y = 20).

Wie geht das?
Zuletzt geändert von ddpf am Donnerstag 6. Juni 2013, 13:21, insgesamt 1-mal geändert.
BlackJack

@ddpf: Ich habe noch nicht so richtig verstanden was Du hast und was Du haben möchtest. Kann es sein, dass Du Deine Getter- und Settermethoden einfach nur in `__getitem__()` und `__setitem__()` umbenennen willst?

Code: Alles auswählen

    print obj.get_register_channel(channel_number)
    obj.set_register_channel(channel_number, value)
    # 
    # -> Umbenennen der Methoden nach `__getitem__()` und `__setitem__()`
    # 
    print obj[channel_number]
    obj[channel_number] = value
ddpf
User
Beiträge: 21
Registriert: Freitag 22. Februar 2013, 12:13

Ungefähr das möchte ich haben. Ich habe bei der betreffenden Klasse eine Datenstruktur (Klasse) vererbt. In dieser Datenstruktur gibt es Register die mittels mehrerer Arrays dargestellt sind. Ich möchte innerhalb der vererbten Datenstruktur ein Element ansprechen. Dieses Element ist ein ctypes-array. Also in deinem Code würde es nur eine Sache geben. Ich habe aber mehrere Elemeente und ein Teil dieser Elemente sind arrays.
Ist es jetzt verständlich?

EDIT: Habe gerade kleinen Fehler gesehen. Ist im Originalposting ausgebessert.
(
object.channel_array[x] = y
output = object.channel_array[x]
)

EDIT2: Ich probiers mal direkt mit Source. Meine Frage: Wie kann ich jetzt ein property machen, sodass ich

Code: Alles auswählen

class data_struct(Structure):
   pass

data_struct._fields_ = [
...
('register', POINTER(c_ulong)*8),
...

Code: Alles auswählen

class C(data_struct):
   def __init__(self)
      data_struct.__init__(self)
      for primary_ptr in (
                self.register
        ):
            register.contents = register._type_()
      ...

   def set_register_channel(self, ch, value):
        self.register[ch][0] = self.register[ch]._type_(value)

   def get_register_channel(self, ch):
      return self.register[ch][0]

   register = property(?,?)#wie geht das?

Code: Alles auswählen

obj = C()
obj.register[2] = 20
print obj.register[2]
Zuletzt geändert von ddpf am Donnerstag 6. Juni 2013, 13:45, insgesamt 4-mal geändert.
BlackJack

@ddpf: Nee, so richtig habe ich es immer noch nicht verstanden. Kannst Du nicht mal ein Beispiel von dem zeigen was Du hast?
ddpf
User
Beiträge: 21
Registriert: Freitag 22. Februar 2013, 12:13

Ich habe oben edited
Sirius3
User
Beiträge: 17737
Registriert: Sonntag 21. Oktober 2012, 17:20

so?

Code: Alles auswählen

class C(data_struct):
   def __init__(self)
      data_struct.__init__(self)
      for primary_ptr in (
                self.register
        ):
            register.contents = register._type_()
      ...

   def __setitem__(self, ch, value):
        self.register[ch][0] = self.register[ch]._type_(value)

   def __getitem__(self, ch):
      return self.register[ch][0]
ddpf
User
Beiträge: 21
Registriert: Freitag 22. Februar 2013, 12:13

Und wie spreche ich jetzt das register genau an?
BlackJack

@dppf: Also `register` kannst Du es schon mal nicht nennen, denn damit würdest Du ja das `register`-Attribut was es schon gibt verdecken. Entweder müsstest Du es anders nennen — registers zum Beispiel — oder Du darfst nicht von `data_struct` erben, sondern müsstest das in def `C`-Klasse per Komposition lösen.

Das würde man dann auch nicht mit einem Property lösen (können), sondern man bräuchte eine Wrapperklasse um das `register`-Array mit den magischen Itemzugriffsmethoden. Also quasi so etwas hier:

Code: Alles auswählen

class _RegisterWrapper(object):
    def __init__(self, register):
        self.register = register

    def __getitem__(self, channel_number):
        return self.register[channel_number][0]

    def __setitem__(self, channel_number, value):
        self.register[channel_number][0] = (
            self.register[channel_number]._type_(value)
        )


class C(data_struct):
    def __init__(self):
        data_struct.__init__(self)
        for primary_ptr in self.register:
            primary_ptr.contents = primary_ptr._type_()

        self.registers = _RegisterWrapper(self.register)


obj = C()
obj.registers[2] = 20
print obj.registers[2]
ddpf
User
Beiträge: 21
Registriert: Freitag 22. Februar 2013, 12:13

EDIT: Ich sehe gerade wie ich es machen muss... werde Lösung gleich posten

Wegen dem keyword register: Habe ich jetzt einfach mal schnell reingeschrieben weil die Namen im Programm anders heißen und die ganze Struktur viel komplizierter ist. Ich hätte da aber noch ein Problem. Ich habe nicht nur eine Registerbank, sondern 2. Da steht genau das Gleiche drinnen. Ist eine Reduntanz. Ich würde in der setter und getter Methode auch gleichzeitig abragen ob das gleiche drinnen ist.
Sprich

Code: Alles auswählen

assert self.register_primary[ch][0] == self.register_secondary[ch][0]; "primary register differs to secondary register of channel {0}".format(ch)

muss beim setter und getter rein.

Um genau zu sein gehört das so:

Code: Alles auswählen

    def set_register_channel(self, ch, value):
        self.register_primary[ch][0] = self.register_primary[ch]._type_(value)
        self.register_secondary[ch][0] = self.register_primary[ch]._type_(value)        
        assert self.register_primary[ch][0] == self.register_secondary[ch][0]; "Primary register differs to secondary register of channel {0}".format(ch)

Code: Alles auswählen

    def get_register_channel(self, ch):
        assert self.register_primary[ch][0] == self.register_secondary[ch][0]; "Primary register differs to secondary register of channel {0}".format(ch)
        return self.register_primary[ch][0]
ddpf
User
Beiträge: 21
Registriert: Freitag 22. Februar 2013, 12:13

Gut, ich habe das jetzt mit dem gespiegelten Register wie folgt gelöst:

Code: Alles auswählen

class _RegisterWrapper(object):
    def __init__(self, register_primary, register_secondary):
        self.register_primary = register_primary
        self.register_secondary = register_secondary

    def __getitem__(self, channel_number):
        assert self.register_primary[channel_number][0] == self.register_secondary[channel_number][0]; "Primary register differs to secondary register of channel {0}".format(channel_number)
        return self.register_primary[channel_number][0]

    def __setitem__(self, channel_number, value):
        self.register_primary[channel_number][0] = self.register_primary[channel_number]._type_(value)
        self.register_secondary[channel_number][0] = self.register_secondary[channel_number]._type_(value)
        assert self.register_primary[channel_number][0] == self.register_secondary[channel_number][0]; "Primary register differs to secondary register of channel {0}".format(channel_number)

Code: Alles auswählen

def __init__(self)
...
   self.registers = _RegisterWrapper(self.register_primary, self.register_secondary)
...

Code: Alles auswählen

        self.obj.registers[0] = 4294967295
        print self.obj.register_primary[0][0]
        print self.obj.register_secondary[0][0]
        print self.obj.registers[0]
Antworten