Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/308.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 使用描述符协议更改基础数据表示_Python - Fatal编程技术网

Python 使用描述符协议更改基础数据表示

Python 使用描述符协议更改基础数据表示,python,Python,假设我有一个现有的类,例如做一些数学方面的事情: 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)) 现在,出于某种原因,我希望Python不像任何变量那样存储成员x和y。我更希望Python在内部将它们存

假设我有一个现有的类,例如做一些数学方面的事情:

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))
现在,出于某种原因,我希望Python不像任何变量那样存储成员
x
y
。我更希望Python在内部将它们存储为字符串。或者它将它们存储到一个专用的缓冲区中,可能是为了与某些C代码的互操作性。因此(对于字符串情况),我构建了以下描述符:

我将现有的vector类包装在一个新类中,其中成员
x
y
变成
MyStringMemory

class StringVector(Vector):

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

    x = MyStringMemory(float)
    y = MyStringMemory(float)
最后,一些驱动代码:

v = StringVector(1, 2)
print(v.norm())
v.x, v.y = 10, 20
print(v.norm())
毕竟,我将
x
y
的内部表示替换为字符串,而没有对原始类进行任何更改,但仍然具有其全部功能

我只是想知道:这个概念会普遍适用吗?还是我会遇到严重的陷阱?正如我所说,主要思想是将数据存储到一个特定的缓冲区位置,稍后由C代码访问


编辑:我的意图如下。目前,我有一个运行良好的程序,其中一些物理对象,所有类型都是
MyPhysicalObj
相互交互。对象中的代码使用Numpy进行矢量化。现在我还想在所有对象上矢量化一些代码。例如,每个对象都有一个
能量
,该能量由每个对象的复杂矢量化代码计算。现在我想总结一下所有的能量。我可以迭代所有对象并求和,但这太慢了。因此,我更希望将每个对象的属性
能量
自动存储到全局预定义的缓冲区中,我可以在该缓冲区上使用
numpy.sum

如果您像以前一样需要通用转换器(“convert”),这是一种方法

当您需要创建大量实例时,最大的缺点将是性能(我假设您可能会这样做,因为类名为
Vector
)。这将很慢,因为python类启动很慢

在这种情况下,您可以考虑使用,您可以看到文档具有与您类似的场景。


作为旁注:如果可能的话,为什么不在init方法上创建一个以x和y为字符串表示的dict呢?然后继续使用x和y作为普通变量,而不进行所有转换

关于python描述符有一个陷阱

使用代码,您将引用分别存储在StringVector.x.prop和StringVector.y.prop中的相同值:

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)
将具有以下输出:

Write
Write
current StringVector "x":  1
Write
Write
current StringVector "x":  3
Read
3.0
Read
3.0
我想这不是你想要的。要在对象内部存储每个对象的唯一值,请进行以下更改:

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))
输出:

Write
Write
Write
Write
Read
Read
1.0 <class 'float'>
1 <class 'str'>
Read
Read
3.0 <class 'float'>
3 <class 'str'>
写入
写
写
写
阅读
阅读
1
1.
阅读
阅读
3
3.
此外,您肯定可以使用描述符的
\uuuuu set\uuu
方法将数据保存在集中式存储中


请参阅本文档:

如果您希望与C代码实现互操作性,请查看Numpy和Cython。您可以通过cython向C/C++发送Numpy缓冲区。我不会把数字转换成字符串,这是一个非常不完善的表示法。哦,太感谢了,我没想到。。。所以在一般的OOP术语中,描述符是类的静态成员?是的。同样在Python中,它们不是静态的(=),可以添加到类中,并在运行时与它们的子对象一起使用。
Write
Write
Write
Write
Read
Read
1.0 <class 'float'>
1 <class 'str'>
Read
Read
3.0 <class 'float'>
3 <class 'str'>