有一种标准方式可以表示在QAbstractItemModels
中使用的数据,其中有一个单独的数据项类,用于存储有关项目的数据及其在模型中的位置。
simpletreemodel示例(在Python中)说明了一种非常标准的方法,其中数据存储在TreeItem
中,该class TreeItem(object):
def __init__(self, data, parent=None):
self.parentItem = parent
self.itemData = data
self.childItems = []
初始化为:
TreeItem
请注意,每个TreeItems
实例都包含其相关的特定于项目的数据(self.itemData),但还有一个子项列表(自身为TreeItem
)及其父项item(也是A
|
|--B
| |--C
| |
| |--D
|
|-E
)作为属性。
为什么这不是一个非常低效的内存使用?让我们关注以下树形图中的项目B:
A.childItems[0]
天真地,一旦构造完整数据树,B的数据似乎将被存储四次。它将由C.parentItem
,D.parentItem
,B.itemData
以及QAbstract*Model
返回。
是否有一些Python魔法让这个不成为低效的内存使用?
注意:即使在TreeItem
被子类化时这些类型的数据容器被大量使用,这些容器本身实际上不包含Qt({{1}}的代码中没有Qt类被子类化)。所以这真的是一个基本的 Python 问题,而不是 Qt 问题。
可能相关的帖子
答案 0 :(得分:3)
在Python中,变量名称是对象的引用,因此所有这些不同的表达式实际上都引用相同的对象,即内存中的相同数据。尽管存在重复的引用,但没有重复的对象。因此,在您的示例中,A.childItems[0]
,C.parentItem
和D.parentItem
都是引用到同一个对象B
。因此,A.childItems[0].itemData
,C.parentItem.itemData
,D.parentItem.itemData
都引用相同的B.itemData
对象。
与神经网络评论中提到的LEGB文章相关的附注:如果A,B,C或D中的任何一个修改itemData
引用的对象(通过调用方法或设置属性或数据)该对象的成员),然后所有其他人将看到更改。但是,如果将A.childItems[0]
,C.parentItem
或D.parentItem
中的任何一个重新分配给其他对象,则只会影响父级:A.childItems[0] = something
仅影响A.childItems
中的第一个元素{1}}; C.parentItem
和D.parentItem
以及B
的任何其他引用仍然引用B
。
您可能会发现Python variable reference assignment上的答案很有用,但我发现它们并不清楚。我更喜欢Is Python pass-by-reference or pass-by-value,看看你的想法。
答案 1 :(得分:1)
正如@schollii和@hank指出的那样,PyQt和PySide是基于C ++的Qt的Python包装器。因此,如果Qt使用对象/指针(如您所描述的树中的父对象和子对象),则Python的对应变量也存储引用或指针对象。因此,内存中没有这些对象的重复,只是重复引用或指向内存中相同内容的指针。
这些链接是关于这个主题的精彩读物: