【问题标题】:Why does .append() not work on this list?为什么 .append() 不适用于此列表?
【发布时间】:2015-09-10 13:21:31
【问题描述】:

我有一个对象scene,它是Scene 类的一个实例,并且有一个children 列表,它返回:

[<pythreejs.pythreejs.Mesh object at 0x000000002E836A90>, <pythreejs.pythreejs.SurfaceGrid object at 0x000000002DBF9F60>, <pythreejs.pythreejs.Mesh object at 0x000000002E8362E8>, <pythreejs.pythreejs.AmbientLight object at 0x000000002E8366D8>, <pythreejs.pythreejs.DirectionalLight object at 0x000000002E836630>]

如果我想用 point 更新此列表,其类型为:

<class 'pythreejs.pythreejs.Mesh'>

我需要执行:

scene.children = list(scene.children) + [point]

通常,我会执行:

scene.children.append(point)

然而,虽然这两种方法都附加了point,但只有第一种方法实际更新了列表并产生了预期的输出(即网格上的体素)。为什么?

完整代码可以在here找到。

【问题讨论】:

  • 不,append 应该可以工作。如果没有,那就是很奇怪的事情,你需要发minimal reproducible example
  • 我明白,不幸的是,我在生成一个发生此问题的最小示例时遇到了一些问题:(...目前试图弄清楚我是否在做一些愚蠢的事情导致这个问题
  • 我能想到的唯一解释是scene.children 实际上不是一个列表,它是实现append 的其他类,但其行为方式与列表不同。如果你把print(type(scene.children)) 放在scene.children.append(point) 前面的那一行,输出是什么?
  • @Kevin - 返回&lt;type 'list'&gt;;注意scene 是类Scenechildren 的实例是列表
  • 您如何检查scene.children 的内容以查看其中是否存在point?您是在append 行之后立即检查,还是稍后再检查?

标签: python list python-2.7 append ipython-notebook


【解决方案1】:

我猜您的问题是由于 childrenproperty(或其他描述符)而不是您正在与之交互的 Scene 实例的简单属性。您可以获取子级列表,或将新的子级列表分配给属性,但您处理的列表实际上并不是类在内部跟踪其子级的方式。如果修改从scene.children 获得的列表,则修改不会反映在类中。

对此进行测试的一种方法是将scene.children 中的列表多次保存在不同的变量中,并查看它们是否都是相同的列表。试试:

a = scene.children
b = scene.children
c = scene.children

print(id(a), id(b), id(c))

我怀疑每个列表你会得到不同的ids。

这是一个演示您所看到的相同问题的课程:

class Test(object):
    def __init__(self, values=()):
        self._values = list(values)

    @property
    def values(self):
        return list(self._values)

    @values.setter
    def values(self, new_values):
        self._values = list(new_values)

每次检查values 属性时,您都会得到一个新的(复制的)列表。

我认为没有与您发现的工作有根本不同的修复方法。您可以通过以下方式简化一些事情:

scene.children += [point]

由于 Python 中 += 运算符的工作原理,这会扩展列表,然后将其重新分配回 scene.children(如果存在 __iadd__ 方法,a += b 等效于 a = a.__iadd__(b))。

【讨论】:

  • 对于abc,建议的打印语句返回相同的id。此外,scene.children+=[point] 不会产生与scene.children=list(scene.children)+[point] 相同的结果。但是,您可能是对的,scene.children 不是一个简单的列表
  • 实际上根据源代码:github.com/jovyan/pythreejs/blob/master/pythreejs/…,代码的作者显然也无法获取实例列表:TODO: figure out how to get a list of instances of Object3d
  • 啊,好吧,也许它以某种方式重用了列表对象。 += 版本的行为究竟如何?它不会改变scene 对象中的任何内容吗?跳过代码中的list 调用而只执行scene.children = scene.children + [point] 是否有效?
  • +=.append() 方法类似,似乎都将point 添加到列表中,但是双击时没有将体素添加到场景中。跳过list 调用确实有效。
【解决方案2】:

根据this 问题,事实证明这是traitlets 问题。除非定义了新列表,否则修改 self.children 的元素不会触发事件通知。

【讨论】:

    猜你喜欢
    • 2010-10-16
    • 2018-02-18
    • 2020-02-03
    • 1970-01-01
    • 1970-01-01
    • 2011-09-20
    • 2015-07-18
    • 2019-11-01
    • 1970-01-01
    相关资源
    最近更新 更多