Change the underlying data representation with the descriptor protocol
<p>Suppose I have an existing class, for example doing some mathematical stuff:</p>

<pre><code>class Vector:

    def __init__(self, x, y):
        self.x = y
        self.y = y

    def norm(self):
        return math.sqrt(math.pow(self.x, 2) + math.pow(self.y, 2))
</code></pre>

<p>Now, for some reason, I'd like to have that Python does not store the members <code>x</code> and <code>y</code> like any variable. I'd rather want that Python internally stores them as strings. Or that it stores them into a dedicated buffer, maybe for interoperability with some C code. So (for the string case) I build the following <em>descriptor</em>:</p>

<pre><code>class MyStringMemory(object):

    def __init__(self, convert):
        self.convert = convert

    def __get__(self, obj, objtype):
        print('Read')
        return self.convert(self.prop)

    def __set__(self, obj, val):
        print('Write')
        self.prop = str(val)

    def __delete__(self, obj):
        print('Delete')
</code></pre>

<p>And I wrap the existing vector class in a new class where members <code>x</code> and <code>y</code> become <code>MyStringMemory</code>:</p>

<pre><code>class StringVector(Vector):

    def __init__(self, x, y):
        self.x = x
        self.y = y

    x = MyStringMemory(float)
    y = MyStringMemory(float)
</code></pre>

<p>Finally, some driving code:</p>

<pre><code>v = StringVector(1, 2)
print(v.norm())
v.x, v.y = 10, 20
print(v.norm())
</code></pre>

<p>After all, I replaced the internal representation of <code>x</code> and <code>y</code> to be strings without any change in the original class, but still with its full functionality.</p>

<p>I just wonder: <strong>Will that concept work universally or do I run into serious pitfalls?</strong> As I said, the main idea is to store the data into a specific buffer location that is later on accessed by a C code.</p>

<p><strong>Edit:</strong> The intention of what I'm doing is as follows. Currently, I have a nicely working program where some physical objects, all of type <code>MyPhysicalObj</code> interact with each other. The code <em>inside</em> the objects is vectorized with Numpy. Now I'd also like to vectorize some code <em>over all</em> objects. For example, each object has an <code>energy</code> that is computed by a complicated vectorized code per-object. Now I'd like to sum up all energies. I can iterate over all objects and sum up, but that's slow. So I'd rather have that property <code>energy</code> for each object automatically stored into a globally predefined buffer, and I can just use <code>numpy.sum</code> over that buffer.</p>

<p>There is one pitfall regarding python descriptors.</p>

<p>Using your code, you will reference the same value, stored in StringVector.x.prop and StringVector.y.prop respectively:</p>

<pre><code>v1 = StringVector(1, 2)
print('current StringVector "x": ', StringVector.__dict__['x'].prop)
v2 = StringVector(3, 4)
print('current StringVector "x": ', StringVector.__dict__['x'].prop)

print(v1.x)
print(v2.x)
</code></pre>

<p>will have the following output:</p>

<pre><code>Write
Write
current StringVector "x":  1
Write
Write
current StringVector "x":  3
Read
3.0
Read
3.0
</code></pre>

<p>I suppose this is not what you want=). To store unique value per object inside object, make the following changes:</p>

<pre><code>class MyNewStringMemory(object):
    def __init__(self, convert, name):
        self.convert = convert
        self.name = '_' + name

    def __get__(self, obj, objtype):
        print('Read')
        return self.convert(getattr(obj, self.name))

    def __set__(self, obj, val):
        print('Write')
        setattr(obj, self.name, str(val))

    def __delete__(self, obj):
        print('Delete')


class StringVector(Vector):
    def __init__(self, x, y):
        self.x = x
        self.y = y

    x = MyNewStringMemory(float, 'x')
    y = MyNewStringMemory(float, 'y')


v1 = StringVector(1, 2)
v2 = StringVector(3, 4)

print(v1.x, type(v1.x))
print(v1._x, type(v1._x))
print(v2.x, type(v2.x))
print(v2._x, type(v2._x))
</code></pre>

<p>Output:</p>

<pre><code>Write
Write
Write
Write
Read
Read
1.0 &lt;class 'float'&gt;
1 &lt;class 'str'&gt;
Read
Read
3.0 &lt;class 'float'&gt;
3 &lt;class 'str'&gt;
</code></pre>

<p>Also, you definitely could save data inside centralized store, using descriptor's <code>__set__</code> method.</p>

<p>Refer to this document: <a href="https://docs.python.org/3/howto/descriptor.html" rel="nofollow">https://docs.python.org/3/howto/descriptor.html</a></p>

python