python - 从内部添加和删除实例到列表

标签 python python-3.x list object

以下代码定义了一个类 (Wall),当它被实例化时,对象被添加到一个列表 (in_progress) 中,一旦它的属性 (progress) 达到 3,它就会从该列表中删除并移动到另一个列表 (built)。

in_progress = []
built = []

class Wall:
    global in_progress, built

    def __init__(self):
        self.progress = 0
        in_progress.append(self)

    def build(self):
        self.progress += 1

        if self.progress == 3:
            in_progress.remove(self)
            built.append(self)

这很方便,因为无论列表“in_progress”中有多少墙,我都可以运行:

for wall in in_progress:
    wall.build()

最终“in_progress”将是空的。但是我做了一些测试,当 in_progress 中的一个实例达到 progress = 3 时,一些奇怪的事情发生了。

例如。让我们实例化三堵墙:

Wall()
Wall()
Wall() 

#check in_progress
in_progress
--->
[<__main__.Wall at 0x7f4b84e68cf8>,
 <__main__.Wall at 0x7f4b84e68c50>,
 <__main__.Wall at 0x7f4b84e68f28>]

#check attribute progress

for wall in in_progress:
    print(f'{wall}: {wall.progress}')
--->
<__main__.Wall object at 0x7f4b84e68cf8>: 0
<__main__.Wall object at 0x7f4b84e68c50>: 0
<__main__.Wall object at 0x7f4b84e68f28>: 0

#'build' on them 2 times
for wall in in_progress:
    wall.build()

for wall in in_progress:
    print(f'{wall}: {wall.progress}')
--->
<__main__.Wall object at 0x7f4b84e68cf8>: 2
<__main__.Wall object at 0x7f4b84e68c50>: 2
<__main__.Wall object at 0x7f4b84e68f28>: 2

如果我们再次运行最后一段代码,我们预计会发现列表 in_progress 是空的,但我们发现的是:

#'build' on them once more
for wall in in_progress:
    wall.build()

for wall in in_progress:
    print(f'{wall}: {wall.progress}')
--->
<__main__.Wall object at 0x7f4b84e68c50>: 2

如果我们检查 build 的列表,我们会发现剩下 2 面墙,但应该有 3 面。 为什么会这样?

最佳答案

您的构建函数中的问题是您试图修改您正在迭代的同一个列表,这导致了这个奇怪的问题发生,尝试如下,您应该看不到这个问题。我正在通过 copy.copy https://docs.python.org/3/library/copy.html 将列表复制到另一个变量

import copy
in_progress = []
built = []

class Wall:
    global in_progress, built

    def __init__(self):
        self.progress = 0
        in_progress.append(self)

    def build(self):
        global in_progress
        self.progress += 1
        #Make a copy of the list and operate on that
        copy_in_progress = copy.copy(in_progress)
        if self.progress == 3:
            copy_in_progress.remove(self)
            built.append(self)
        in_progress = copy_in_progress

Wall()
Wall()
Wall()

print(in_progress)
#[<__main__.Wall object at 0x108259908>, 
#<__main__.Wall object at 0x108259940>, 
#<__main__.Wall object at 0x1082599e8>]

for wall in in_progress:
    print(f'{wall}: {wall.progress}')

#<__main__.Wall object at 0x108259908>: 0
#<__main__.Wall object at 0x108259940>: 0
#<__main__.Wall object at 0x1082599e8>: 0

for wall in in_progress:
    wall.build()
    wall.build()

for wall in in_progress:
    print(f'{wall}: {wall.progress}')


#<__main__.Wall object at 0x108259908>: 2
#<__main__.Wall object at 0x108259940>: 2
#<__main__.Wall object at 0x1082599e8>: 2
for wall in in_progress:
    wall.build()

for wall in in_progress:
    print(f'{wall}: {wall.progress}')
#Nothing is printed

关于python - 从内部添加和删除实例到列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55506417/

相关文章:

c# - 在新对象声明中使用 foreach

python - 在 Python 中将输入函数参数放入字典的最佳方法是什么?

python-3.x - KivyMD 中 MDDropdownMenu 的定位错误

c# - 根据 C# 中的条件从 List<T> 中删除重复项

python - 了解 Python 中的 UnboundLocalError

image - 是否可以放置图像而不是按钮,并使其可点击?

python - 提取每个子列表的第一项

python - Python 中将字节转换为 int32_t 列表的最快方法

python - 如何在python中使用dir()区分数据成员和函数成员?

python - 从 Python 和 happybase/Thrift 连接到 Hbase