假设我有一个现有的类,例如做一些数学的东西:
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代码的互操作性。所以(对于字符串情况)我构建了以下描述符:
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')
我将现有的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进行矢量化。现在,我还想在所有对象上呈现一些代码。例如,每个对象都有一个energy
,它由每个对象的复杂矢量化代码计算。现在我想总结一切能量。我可以迭代所有对象并总结,但这很慢。所以我宁愿将每个对象的属性energy
自动存储到全局预定义的缓冲区中,我只能在该缓冲区上使用numpy.sum
。
答案 0 :(得分:1)
关于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'>
此外,您绝对可以使用描述符的__set__
方法将数据保存在集中存储中。
答案 1 :(得分:0)
如果你需要一个通用转换器(&#39;转换&#39;)就像你一样,这就是你要走的路。
当您需要创建大量实例时,最大的缺点将是性能(我认为您可能会因为类Vector
而这样)。由于python类启动缓慢,因此速度很慢。
在这种情况下,您可以考虑使用namedTuple,您可以看到文档与您拥有的场景类似。
作为旁注:如果可能,为什么不在init方法上创建一个带有x和y字符串表示的dict?然后继续使用x和y作为正常变量而不进行所有转换