Reputation: 3188
I'm trying to create an object in python which is composed of smaller objects. Each of the objects has its own meaning - each of the smaller objects and the entire object as a whole. The problem is that I want each of the 3 objects to be seemingly independently addressable and to operate as standalone objects and this is rather difficult to achieve. This problem would be easy to solve in C using pointers but I find it difficult to simulate this behavior in Python.
An example to the situation I'm talking about could be seen in a control word of a state machine: The control word (2 bytes) has a meaning as a whole and needs to be accesses (or transferred) as an object, but each of the bytes in the control word has its own meaning and needs to be set and accessed independently.
In C I'd do something like:
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;
And thus I'd be able to access each of the elements easily and not be forced to maintain complex logic to keep all 3 objects in sync - an assignment into *control_word
would update both low_byte
and high_byte
simultaneously, and any update to the byte objects will influence the control_word
.
Is there a simple way to achieve this behavior in Python?
Upvotes: 1
Views: 147
Reputation: 76057
Two alternatives:
You can use C and a CPython wrapper... Or you can use properties:
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)
now you can use it as:
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
given the further explanation from the comments:
I'd want to be able to do something like
c = Control(); device_control = dict(device_control = c.word, device_read_permissions = c.low, device_write_permissions = c.high)
and then access each component through the dict...
you don't need the dictionary at all, you can make our Control
class to behave like a dictionary implementing the dict
protocol (it has quite a few methods, you can leave out those that you are not using if you want):
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
and then use it like this:
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'
Upvotes: 4
Reputation: 91028
To access parts AND to extract the objects, you should create some "part objects".
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)
Untested, but should give you an idea how to proceed.
Upvotes: 1
Reputation: 599600
If I understand you correctly, this is extremely easy to achieve in Python.
my_obj1 = Object1()
my_obj2 = Object2()
my_parent_obj = Object3()
my_parent_obj.obj1 = my_obj1
my_parent_obj.obj2 = my_obj2
Now the object1 and object2 instances are addressable both independently as my_obj1
and as part of the parent object as my_parent_obj.obj1
. Any change you make to one will affect the other.
Upvotes: -1