Создание питонических объектов, которые разделяют память

1

Я пытаюсь создать объект в python, который состоит из меньших объектов. Каждый из объектов имеет свой собственный смысл - каждый из меньших объектов и всего объекта в целом. Проблема в том, что я хочу, чтобы каждый из трех объектов был, по-видимому, независимо адресуемым и работал как автономные объекты, и этого довольно сложно достичь. Эту проблему можно было бы легко решить в 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;

И, таким образом, я мог бы легко получить доступ к каждому *control_word и не будет вынужден поддерживать сложную логику, чтобы синхронизировать все 3 объекта - назначение в *control_word одновременно обновляло как low_byte и high_byte, и любое обновление для объектов байта будет влиять на control_word.

Есть ли простой способ добиться такого поведения в Python?

Теги:
pointers

3 ответа

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) c = Control(); device_control = dict(device_control = c.word, device_read_permissions = c.low, device_write_permissions = c.high) а затем доступ к каждому компоненту через dict...

вам совсем не нужен словарь, вы можете заставить наш класс Control вести себя как словарь, реализующий dict протокол (у него есть довольно много методов, вы можете оставить те, которые вы не используете, если хотите):

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'
  • 0
    Это кажется довольно хорошим, но могу ли я получить low и high как самостоятельный объект? То есть извлечь их из класса? Или я должен просто воссоздать свойство из класса, предоставив связанные методы для функции свойства?
  • 0
    Вы хотите передать их по ссылке, чтобы другие могли обновить их, не имея ссылки на весь объект Control ? Боюсь, что нет, если вы не оберните их в другой изменяемый объект.
Показать ещё 6 комментариев
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)

Непроверенный, но должен дать вам представление о том, как действовать.

  • 0
    циклические ссылки все еще лучше избегать вообще в Python ...
-2

Если я правильно вас понимаю, это очень легко достичь в 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. Любое изменение, которое вы делаете на один, повлияет на другое.

  • 1
    Проблема здесь в том, что родительский объект не является непрерывным в памяти, и это решение на самом деле не имитирует мой данный пример. Он не будет работать для целых чисел, не перегружая оператор присваивания родительского объекта, чтобы разделить входные данные между дочерними объектами и что-то придумать, когда вы попытаетесь получить значение для соединения двух дочерних объектов в один снова ... Я обновил мой вопрос, чтобы подчеркнуть это.
  • 3
    Может быть, вы ищете property ( docs.python.org/library/functions.html#property )?

Ещё вопросы

Сообщество Overcoder
Наверх
Меню