我发现了Python 3.7.2的这种奇怪行为(我还没有尝试过其他版本)。我创建了以下案例,希望能更好地了解情况。
我想编写一个Object Inventory类,其中包括一个记录器类,该类将当前库存记录在柜台上(例如每天)。然后,我想使用记录器类在某一天检索库存。
代码如下:
class Obj():
def __init__(self, parameter):
self.par = parameter
class ObjInventory():
def __init__(self, object_list):
self.list_of_objects = object_list
self.counter = 0
self.logger = InventoryLogger()
def increase_counter(self):
self.logger.add_list_at_counter(self.counter, self.list_of_objects)
self.counter += 1
class InventoryLogger():
def __init__(self):
self.dict_of_positions = {}
def add_list_at_counter(self, counter, object_list):
self.dict_of_positions[counter] = object_list
def print_object_inventory_on_count(self, counter):
object_list = self.dict_of_positions[counter]
list_of_parameters = [object.par for object in object_list]
print(list_of_parameters)
Inventory = ObjInventory([])
first_list_of_objects = [Obj(1), Obj(2), Obj(3)]
Inventory.list_of_objects += first_list_of_objects
Inventory.increase_counter()
Inventory.logger.print_object_inventory_on_count(0)
second_list_of_objects = [Obj(4), Obj(5), Obj(6)]
Inventory.list_of_objects += second_list_of_objects
Inventory.increase_counter()
Inventory.logger.print_object_inventory_on_count(1)
del Inventory.list_of_objects[2:4]
Inventory.increase_counter()
Inventory.logger.print_object_inventory_on_count(2)
Inventory.logger.print_object_inventory_on_count(0)
Inventory.logger.print_object_inventory_on_count(1)
Inventory.logger.print_object_inventory_on_count(2)
预期结果将是这样:
[1, 2, 3] #---> first 3 objects
[1, 2, 3, 4, 5, 6] #---> first 3 objects and additional 3 objects
[1, 2, 5, 6] #---> list without removed objects
[1, 2, 3] #reiteration
[1, 2, 3, 4, 5, 6]
[1, 2, 5, 6]
但是我得到的是这样的:
[1, 2, 3]
[1, 2, 3, 4, 5, 6]
[1, 2, 5, 6]
[1, 2, 5, 6]
[1, 2, 5, 6]
[1, 2, 5, 6]
因此,记录器打印仅在直接调用后才起作用。如果我稍后再调用记录器功能,则所有词典条目将等于最后一个条目。
我通过以下方法修改add_list_at_counter函数找到了一种解决方法,这会导致所需的代码响应:
def add_list_at_counter(self, counter, object_list):
self.dict_of_positions[counter] = []
self.dict_of_positions[counter] += object_list
尤其是变通方法(我在几个小时后试图了解代码为什么不起作用的发现)使我感到困惑。关于第二个代码为何有效而第一个代码无效的任何想法吗?还是某种错误?
答案 0 :(得分:1)
您的问题是由以下事实引起的:您的记录器中的字典中的许多列表值实际上都是对同一list_of_objects
的引用。
将其与以下代码进行比较:
x = [1,2,3] # x refers to a list
y = x # y is another reference to the same list
x.append(4) # modify the list through x
print(y) # prints [1, 2, 3, 4], even though we accessed via y
您的代码在做相同的事情,但是您不是通过诸如x
和y
这样的简单变量,而是通过属性和字典值(Inventory.list_of_objects
和{{1 }}(每个Inventory.logger.dict_of_positions[counter]
值)。
我不完全了解您的代码应该做什么,但是我怀疑您可以通过更改counter
以使用{{1创建一个increase_counter
列表的副本来避免此问题。 }}构造函数:
list_of_objects