python - 合适的数据类型来保存指向 numpy ndarray 元素的指针
问题描述
对于一个 python 项目,我的任务是结合两个同事的工作并调用他们的函数。要将问题分解为本质,请考虑以下情况:
同事 A 在他的模块“body_class.py”中计算对象的位置和速度值,如下所示:
class Body:
def __init__(self, x, y, z, vx, vy, vz):
self.x = x
self.y = y
self.z = z
self.vx = vx
self.vy = vy
self.vz = vz
对于他编写的其他函数,他希望尽可能保持代码简洁,并用它们各自的名称调用位置和速度向量的分量。出于这个原因,他将它们保存为单独的变量。
同事 B 需要使用所有Body对象的位置和速度值来进行一些时间紧迫的计算,因此他决定使用 numpy ndarrays 来实现更快的矩阵计算。他期望的工作输入是一个 2D numpy ndarray,其中包含所有Body对象的所有位置和速度分量,形式为(三个Body对象的示例):
state = np.array([[2, 0, 3, -2, 0, -3], #Body 1
[0, 0, 1, 1, 0, 0], #Body 2
[0, 5, 2, 4, 3, 2]]) #Body 3
有没有办法将使用面向对象的实例变量进行同事 A 的操作的代码清晰度与 numpy 用于同事 B 的计算的效率优势结合起来?我最初的想法是将包含所有对象的位置和速度信息的 ndarray 保存为类Body的类变量(以便同事 B 可以轻松访问此变量“状态”),类似于:
class Body:
states = np.empty([0,6])
def __init__(self, x, y, z, vx, vy, vz):
self.x = x
self.y = y
self.z = z
self.vx = vx
self.vy = vy
self.vz = vz
Body.states = np.concatenate((self.states, np.array([[self.x, self.y, self.z, self.vx, self.vy, self.vz]])), axis=0)
...然后为每个 Body 对象创建一个实例变量,该变量仅包含指向相应 ndarray 元素的指针/引用(以便同事 A 可以通过例如从类内部调用self.x来访问变量,而无需不断更新这个实例变量和相应的 ndarray 元素),但我不知道这是否可以在 Python 中实现,更不用说这对于这种情况是否是一个很好的解决方案,或者最好的解决方案是否只是一个两种可能性(ndarray VS实例变量)
欢迎任何想法和建议!在此先感谢您的帮助!
更新:
该项目是一个模拟,因此上述两个操作在模拟的每个时间步执行,这使得性能成为问题。所以我正在寻找一种解决方案,它可以将所有 Body 对象的位置和速度值直接存储在一个大的 2D 数组中(这是同事 B 所需的输入),同时仍然可以通过它们的对象实例访问它们名称(例如 b1.x)或其他更有意义的名称,而不必使用数组索引,例如 state[3,2]。
我想防止的是必须首先在它们的实例属性中设置每个 Body 实例的位置和速度值,然后必须通过循环遍历所有 Body 实例并堆叠在每个时间步骤中再次构造大的 2D 数组“状态”他们各自的位置和速度值一起(据我了解,这对性能非常不利,但如果我错了,请纠正我)
解决方案
听起来像是命名元组的工作:
from collections import namedtuple
Body = namedtuple('Body', ['x', 'y', 'z', 'vx', 'vy', 'vz'])
b1 = Body(2,0,3,-2,0,3)
# now it is possible to access attributes both by name...
b1.x # returns 2
# ... and as an array
np.array(b1) # array([ 2, 0, 3, -2, 0, 3])
UPD:子类化和跟踪对象实例 PoC
_Body = namedtuple('Body', ['x', 'y', 'z', 'vx', 'vy', 'vz'])
class Body(_Body):
instances = set()
def __new__(cls, *args, **kwargs):
body = super(Body, cls).__new__(cls, *args, **kwargs)
Body.instances.add(body)
return body
def __del__(self):
Body.instances.remove(self)
def xy(self):
return self.x + self.y
@classmethod
def states(cls):
# will return a 2D numpy array of all Body instances
return np.array(list(cls.instances))
推荐阅读
- powershell - 在 Citrix Receiver/Workspace 的 ICA 客户端对象 API 中,设置 OutputMode 真的有效吗?
- java - Stax 解析两次
- spring - Spring Boot中的Hibernate Search集成测试问题
- time-series - Python时间序列拆分
- asp.net-core - 如何从 NuGet 安装 Microsoft.AspNetCore.Mvc.Core 版本 3.1.0?
- java - 如何使用 java-11(或 corretto-11)解决 java.lang.NoClassDefFoundError: javax/xml/bind/DatatypeConverter?
- python - Dask 中是否有类似共享内存的东西用于大型对象多处理作业?
- java - 无法找到错误 - 使用递归的二进制搜索
- javascript - 修改 Chrome 应用程序中的用户代理标头
- css - 如果可见性没有过渡,为什么要对不透明度应用过渡?