我正在尝试在python中创建一个由较小对象组成的对象。每个对象都有自己的含义 - 每个较小的对象和整个对象作为一个整体。 问题是我希望3个对象中的每一个看似独立可寻址并作为独立对象运行,这很难实现。 使用指针在C中很容易解决这个问题,但我发现在Python中很难模拟这种行为。
我正在谈论的情况的一个例子可以在状态机的控制字中看到:控制字(2字节)作为一个整体有意义,需要作为对象访问(或转移) ,但控制字中的每个字节都有其自己的含义,需要独立设置和访问。
在C中我会做类似的事情:
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;
因此,我可以轻松访问每个元素,而不是被迫维护复杂的逻辑以保持所有3个对象同步 - 分配到*control_word
将同时更新low_byte
和同时high_byte
,对字节对象的任何更新都会影响control_word
。
是否有简单方法在Python中实现此行为?
答案 0 :(得分:4)
两种选择:
您可以使用C和CPython包装器......或者您可以使用属性:
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)
现在您可以将其用作:
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
鉴于评论的进一步解释:
我希望能够做类似的事情
c = Control(); device_control = dict(device_control = c.word, device_read_permissions = c.low, device_write_permissions = c.high)
然后通过dict访问每个组件...
你根本不需要字典,你可以使我们的Control
类表现得像实现dict
protocol的字典(它有很多方法,你可以省略那些你如果你愿意,不要使用):
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
然后像这样使用它:
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'
答案 1 :(得分:1)
要访问零件并提取对象,您应该创建一些“零件对象”。
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)
未经测试,但应该让您知道如何继续。
答案 2 :(得分:-1)
如果我理解正确,这在Python中很容易实现。
my_obj1 = Object1()
my_obj2 = Object2()
my_parent_obj = Object3()
my_parent_obj.obj1 = my_obj1
my_parent_obj.obj2 = my_obj2
现在,object1和object2实例既可以作为my_obj1
单独寻址,也可以作为my_parent_obj.obj1
作为父对象的一部分进行寻址。您对其中的任何更改都会影响另一方。