对象清单类(包括记录器类)将覆盖字典条目

时间:2019-01-31 20:27:16

标签: python python-3.x dictionary object logging

我发现了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

尤其是变通方法(我在几个小时后试图了解代码为什么不起作用的发现)使我感到困惑。关于第二个代码为何有效而第一个代码无效的任何想法吗?还是某种错误?

1 个答案:

答案 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

您的代码在做相同的事情,但是您不是通过诸如xy这样的简单变量,而是通过属性和字典值(Inventory.list_of_objects和{{1 }}(每个Inventory.logger.dict_of_positions[counter]值)。

我不完全了解您的代码应该做什么,但是我怀疑您可以通过更改counter以使用{{1创建一个increase_counter列表的副本来避免此问题。 }}构造函数:

list_of_objects