我不得不说我真的没有问题,因为“一切正常”,但我很难理解为什么。
我正在用 python/urwid 编写脚本。在我的脚本中,我有一个 ItemWidget 类,其 self._w 等于 3 个小部件的 urwid.Pile,每个小部件都是一行 urwid.Text。此外,类 ItemWidget 有一个属性 self.visibility,它是三个 bool 值的列表,还有一个方法 self.rebuild()。初始化函数是
def __init__ (self, content,vis):
self.content = content
self.visibility = vis
self.rebuild()
self.__super.__init__(self._w)
rebuild() 方法根据 self.visibility() 中的值重建 self._w。
在脚本的 main() 函数中,我有一个变量
globalvisibility = [1,1,1]
我创建了一个包含(大约 1000 个)ItemWidget 实例的列表:
for content in abstracts: # (*)
items.append(ItemWidget(content,globalvisibility)) #
事实上我使用了一个变量而不是
for content in abstracts.items():
items.append(ItemWidget(content,[1,1,1]))
只是因为稍后我将实现将全局可见性保存到文件中。但我认为除了初始化之外它不会有任何用处。
无论如何,在脚本中我经常获取 ItemWidget 的实例并通过例如更改其可见性
item.visibility[2] = 0 # (**)
和类似的。到目前为止,一切正常且符合预期。
这是我的问题。为什么在通过 (*) 创建 ItemWidget 实例后,将变量 globalvisibility 更改为 [0,1,1] 会影响所有这些实例?
我不得不说我偶然“发现”了它,它似乎非常有用(我认为要更改 ItemWidget 所有实例的可见性属性,我必须循环遍历所有实例),但是 - 对我来说 - 非常有用奇怪。特别是考虑到操作 (**) 仅影响单个实例。
我非常感谢一些解释。
编辑:整个脚本在这里: https://www.dropbox.com/s/a0a4a0asyi5lyxw/tescik.py?dl=0 以及示例数据库,如果 itemwidget 是: https://www.dropbox.com/s/zuwbvggznst85ru/arxiv-2013-05-23.db?dl=0
为了运行它,您需要修改第 58 行以指向数据库。要查看行为,请滚动到某些项目并按 Enter 键 - 摘要将仅在这些项目上消失,然后按“显示摘要” - 这将重置所有项目的行为。
最佳答案
Why after creating the instances of ItemWidget via (*), changing the variable globalvisibility to, say, [0,1,1] affects all these instances?
因为您在创建所有这些实例时传递了globalvisibility
。所有实例都在其 vis
属性中存储对同一列表的引用。
如果您想避免这种情况,请在 __init__
方法中或在创建实例时复制该列表:
def __init__ (self, content,vis):
self.content = content
self.visibility = vis[:] # here
# etc.
或者:
for content in abstracts:
items.append(ItemWidget(content, globalvisibility[:]))
您在此处所做的确切选择取决于您是否想要当前的行为。如果是这样,请将其保留在 __init__()
之外,并在创建实例时进行复制。
关于python - 类变量的难以理解的行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28309279/