创建共享内存的pythonic对象

时间:2011-11-18 12:51:57

标签: python c pointers

我正在尝试在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中实现此行为?

3 个答案:

答案 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作为父对象的一部分进行寻址。您对其中的任何更改都会影响另一方。