разделить строку между двумя объектами - PullRequest
1 голос
/ 05 августа 2010

Я хочу, чтобы два объекта разделяли один строковый объект. Как передать строковый объект от первого ко второму так, чтобы любые изменения, примененные одним, были видны другому? Я предполагаю, что мне нужно было бы обернуть строку в своего рода буферный объект и сделать все возможное, чтобы заставить его работать.

Однако у меня есть склонность задумываться над проблемами, поэтому, несомненно, есть более простой путь. Или, может быть, разделение строки - неправильный путь? Имейте в виду, что я хочу, чтобы оба объекта могли редактировать строку. Есть идеи?

Вот пример решения, которое я мог бы использовать:

class Buffer(object):
    def __init__(self):
        self.data = ""
    def assign(self, value):
        self.data = str(value)
    def __getattr__(self, name):
        return getattr(self.data, name)

class Descriptor(object):
    def __get__(self, instance, owner):
        return instance._buffer.data
    def __set__(self, instance, value):
        if not hasattr(instance, "_buffer"):
            if isinstance(value, Buffer):
                instance._buffer = value
                return
            instance._buffer = Buffer()
        instance._buffer.assign(value)

class First(object):
    data = Descriptor()
    def __init__(self, data):
        self.data = data
    def read(self, size=-1):
        if size < 0:
            size = len(self.data)
        data = self.data[:size]
        self.data = self.data[size:]
        return data

class Second(object):
    data = Descriptor()
    def __init__(self, data):
        self.data = data
    def add(self, newdata):
        self.data += newdata
    def reset(self):
        self.data = ""
    def spawn(self):
        return First(self._buffer)

s = Second("stuff")
f = s.spawn()
f.data == s.data
#True
f.read(2)
#"st"
f.data
# "uff"
f.data == s.data
#True
s.data
#"uff"
s._buffer == f._buffer
#True

Опять же, это выглядит как абсолютное излишество из-за простой проблемы. Кроме того, он требует использования класса Buffer, дескриптора и навязываемой переменной _buffer дескриптора.

Альтернативой является назначение одного из объектов, отвечающих за строку, а затем предоставление ему интерфейса для внесения изменений в строку. Более простой, но не совсем тот же эффект.

Ответы [ 3 ]

2 голосов
/ 05 августа 2010

Я хочу, чтобы два объекта совместно использовали один строковый объект.

Они будут, если вы просто передадите строку - Python не копирует, если вы не скажете ему скопировать.

Как передать строковый объект от первого ко второму так, чтобы любые изменения, примененные одним, были видны другому?

Не может никогда быть любым изменением, сделанным в строковом объекте (оно неизменяемое!), Поэтому ваше требование выполняется тривиально (поскольку ложное предусловие подразумевает что угодно).

Я предполагаю, что мне придется обернутьстроку в виде буфера объекта и делать все виды сложности, чтобы заставить его работать.

Вы можете использовать (при условии, что это Python 2 и вам нужна строка байтов) array.array с типом кода c.Массивы являются изменяемыми, так что вы действительно можете их изменить (с помощью методов с мутацией - и некоторых операторов, которые являются особым случаем методов, так как они вызывают специальные методы для объекта).У них нет бесчисленного множества неизменяемых методов строк, поэтому, если они вам нужны, вам действительно понадобится простая оболочка (делегирование указанных методов в str(...) массива, который также содержит оболочка).

Кажется, не должно быть никакой особой сложности, если, конечно, вы не хотите сделать что-то действительно странное, как вы, кажется, дали свой пример кода (есть назначение , то есть * повторное связывание имени магическим образом влияет на другое имя - это не имеет абсолютно никакого отношения к объекту, который ранее был связан с именем, которое вы привязываете, и не изменяет этот объект вв любом случае - единственный объект, который он «меняет» - это , содержащий атрибут, поэтому очевидно, что вам нужны дескрипторы или другая магия для указанного объекта).

Вы, кажется, пришли изнекоторый язык, где переменные (и особенно строки) являются «контейнерами данных» (например, C, Fortran или C ++).В Python (как, скажем, в Java) имена (предпочтительный способ называть то, что другие называют «переменными») всегда просто относятся к объектам, они не содержат ничего, кромеименно такая ссылка.Некоторые объекты могут быть изменены, некоторые - нет, но это абсолютно не связано с оператором присваивания (см. Примечание 1) (который не изменяет объекты: он связывает имена).

(примечание 1): за исключением того, что повторное связывание атрибута или элемента действительно изменяет объект, который «содержит» этот элемент или атрибут - объекты могут и действительно содержать, это names , которые этого не делают.

2 голосов
/ 05 августа 2010

Просто поместите ваше значение для совместного использования в список и назначьте список обоим объектам.

class A(object):
    def __init__(self, strcontainer):
        self.strcontainer = strcontainer
    def upcase(self):
        self.strcontainer[0] = self.strcontainer[0].upper()
    def __str__(self):
        return self.strcontainer[0]

# create a string, inside a shareable list
shared = ['Hello, World!']
x = A(shared)
y = A(shared)

# both objects have the same list
print id(x.strcontainer)
print id(y.strcontainer)

# change value in x
x.upcase()

# show how value is changed in both x and y
print str(x)
print str(y)

Печать:

10534024
10534024
HELLO, WORLD!
HELLO, WORLD!
1 голос
/ 05 августа 2010

Я не большой специалист по Python, но я думаю, что если вы объявите переменную в модуле и добавите в модуль метод получения / установки для этой переменной, вы сможете поделиться им таким образом.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...