开发者

sharing a string between two objects

I want two objects to share a single string object. How do I pass the string object from the first to the second such that any changes applied by one will be visible to the other? I am guessing that I would have to wrap the string in a sort of buffer object and do all sorts of complexity to get it to work.

However, I have a tendency to overthink problems, so undoubtedly there is an easier way. Or maybe sharing the string is the wrong way to 开发者_开发知识库go? Keep in mind that I want both objects to be able to edit the string. Any ideas?

Here is an example of a solution I could use:

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

Again, this seems like absolute overkill for what seems like a simple problem. As well, it requires the use of the Buffer class, a descriptor, and the descriptor's impositional _buffer variable.

An alternative is to put one of the objects in charge of the string and then have it expose an interface for making changes to the string. Simpler, but not quite the same effect.


I want two objects to share a single string object.

They will, if you simply pass the string -- Python doesn't copy unless you tell it to copy.

How do I pass the string object from the first to the second such that any changes applied by one will be visible to the other?

There can never be any change made to a string object (it's immutable!), so your requirement is trivially met (since a false precondition implies anything).

I am guessing that I would have to wrap the string in a sort of buffer object and do all sorts of complexity to get it to work.

You could use (assuming this is Python 2 and you want a string of bytes) an array.array with a typecode of c. Arrays are mutable, so you can indeed alter them (with mutating methods -- and some operators, which are a special case of methods since they invoke special methods on the object). They don't have the myriad non-mutating methods of strings, so, if you need those, you'll indeed need a simple wrapper (delegating said methods to the str(...) of the array that the wrapper also holds).

It doesn't seem there should be any special complexity, unless of course you want to do something truly weird as you seem to given your example code (have an assignment, i.e., a *rebinding of a name, magically affect a different name -- that has absolutely nothing to do with whatever object was previously bound to the name you're rebinding, nor does it change that object in any way -- the only object it "changes" is the one holding the attribute, so it's obvious that you need descriptors or other magic on said object).

You appear to come from some language where variables (and particularly strings) are "containers of data" (like C, Fortran, or C++). In Python (like, say, in Java), names (the preferred way to call what others call "variables") always just refer to objects, they don't contain anything except exactly such a reference. Some objects can be changed, some can't, but that has absolutely nothing to do with the assignment statement (see note 1) (which doesn't change objects: it rebinds names).

(note 1): except of course that rebinding an attribute or item does alter the object that "contains" that item or attribute -- objects can and do contain, it's names that don't.


Just put your value to be shared in a list, and assign the list to both objects.

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)

Prints:

10534024
10534024
HELLO, WORLD!
HELLO, WORLD!


i am not a great expert in python, but i think that if you declare a variable in a module and add a getter/setter to the module for this variable you will be able to share it this way.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜