J'essaie de créer un objet en python qui est composé d'objets plus petits. Chacun des objets a sa propre signification - chacun des petits objets et l'objet entier dans son ensemble. Le problème est que je veux que chacun des 3 objets soit adressable en apparence indépendamment et fonctionne comme des objets autonomes et c'est assez difficile à réaliser. Ce problème serait facile à résoudre en C à l'aide de pointeurs mais je trouve difficile de simuler ce comportement en Python.

Un exemple de la situation dont je parle pourrait être vu dans un mot de contrôle d'une machine d'état: le mot de contrôle (2 octets) a une signification dans son ensemble et doit être des accès (ou transférés) en tant qu'objet, mais chacun des octets du mot de contrôle a sa propre signification et doit être défini et accessible indépendamment.

En C, je ferais quelque chose comme:

unsigned short control_word_memory;
unsigned short *control_word = &control_word_memory;
unsigned char *low_byte = &control_word_memory;
unsigned char *high_byte = low_byte + 1;

Et ainsi je serais en mesure d'accéder facilement à chacun des éléments et de ne pas être obligé de maintenir une logique complexe pour garder les 3 objets synchronisés - une affectation dans *control_word mettrait à jour low_byte et {{X2 }} simultanément, et toute mise à jour des objets d'octet influencera le control_word.

Existe-t-il un moyen pour obtenir ce comportement en Python?

1
immortal 18 nov. 2011 à 16:51

3 réponses

Meilleure réponse

Deux alternatives:

Vous pouvez utiliser C et un wrapper CPython ... Ou vous pouvez utiliser des propriétés:

class Control(object):
        def __init__(self, word=0):
                self.word = word
        def get_low(self):
                return self.word & 0xFF
        def set_low(self, x):
                self.word &= 0xFF00
                self.word |= x & 0xFF
        def get_high(self):
                return (self.word >> 8) & 0xFF
        def set_high(self, x):
                self.word &= 0x00FF
                self.word |= (x & 0xFF) << 8
        low = property(get_low, set_low)
        high = property(get_high, set_high)

Vous pouvez maintenant l'utiliser comme:

In [3]: c = Control(0x1234)

In [4]: hex(c.low)
Out[4]: '0x34'

In [5]: hex(c.high)
Out[5]: '0x12'

In [6]: c.low=56

In [7]: hex(c.word)
Out[7]: '0x1238'

In [8]: c.low=0x56

In [9]: hex(c.word)
Out[9]: '0x1256'

In [10]: c.high = 0x78

In [11]: hex(c.word)
Out[11]: '0x7856'

In [12]: c.word = 0xFE0A

In [13]: c.low
Out[13]: 10

In [14]: c.high
Out[14]: 254

Compte tenu des explications complémentaires des commentaires:

Je voudrais pouvoir faire quelque chose comme c = Control (); device_control = dict (device_control = c.word, device_read_permissions = c.low, device_write_permissions = c.high) puis accédez à chaque composant via le dict ...

Vous n'avez pas du tout besoin du dictionnaire, vous pouvez faire en sorte que notre classe Control se comporte comme un dictionnaire implémentant la dict protocole (il a plusieurs méthodes, vous pouvez laisser de côté celles que vous n'utilisez pas si vous le souhaitez):

class DictControl(Control):
        def __len__(self):
                return 3
        def __getitem__(self, k):
                if k == 'device_control':
                        return self.word
                elif k == 'device_read_permissions':
                        return self.low
                elif k == 'device_write_permissions':
                        return self.high
                else: raise KeyError
        def __setitem__(self, k, v):
                if k == 'device_control':
                        self.word = v
                elif k == 'device_read_permissions':
                        self.low = v
                elif k == 'device_write_permissions':
                        self.high = v
                else: raise KeyError

Puis utilisez-le comme ceci:

In [2]: c = DictControl()

In [3]: c.word = 0x1234

In [4]: hex(c['device_control'])
Out[4]: '0x1234'

In [5]: c['device_read_permissions'] = 0xFF

In [6]: c.low
Out[6]: 255

In [7]: c.high = 0xAA

In [8]: c['device_write_permissions']
Out[8]: 170

In [9]: hex(c.word)
Out[9]: '0xaaff'
4
fortran 18 nov. 2011 à 16:39

Pour accéder aux pièces ET pour extraire les objets, vous devez créer des "objets pièces".

class Part(object):
    def __init__(self, ref, bitstart, bitlen):
        self.ref = ref
        self.bitstart = bitstart
        self.bitlen = bitlen
        self.mask = ((1 << bitlen) - 1) << bitstart
    def set(self, value):
        self.ref.word = self.ref.word & ~self.mask | ((value << self.bitstart) & self.mask)
    def get(self):
        return (self.ref.word & self.mask) >> self.bitstart

class Control(object):
    def __init__(self, word=0):
        self.word = word
        self.low = Part(self, 0, 8)
        self.high = Part(self, 8, 8)

Non testé, mais devrait vous donner une idée de la marche à suivre.

1
glglgl 18 nov. 2011 à 13:44

Si je vous comprends bien, c'est extrêmement facile à réaliser en Python.

my_obj1 = Object1()
my_obj2 = Object2()
my_parent_obj = Object3()
my_parent_obj.obj1 = my_obj1
my_parent_obj.obj2 = my_obj2

Les instances object1 et object2 sont désormais adressables indépendamment en tant que my_obj1 et en tant que partie de l'objet parent en tant que my_parent_obj.obj1. Tout changement que vous apportez à l'un affectera l'autre.

-1
Daniel Roseman 18 nov. 2011 à 12:55
8182714