这段python代码中用了字典的嵌套,为什么同一个变量输出结果会不一样?

这段python代码中用了字典的嵌套,为什么同一个变量输出结果会不一样?感觉第二个输出的结果里最后一组数值,把前面的数值都覆盖了。不知道是为什么。怎么样才能在第二个输出里得到每一组的正确数值。


class Backtest:
  def __init__(self, n) -> None:
    self.n:int =3
    self.atr_list:dict[str, dict]={}
    self.atrs:dict[str, dict]={}

  def run_testing(self):
      for product in ['apple','orange','banana','lemon']:
        self.sample_group(product,self.n)
        self.n += 1
      print("在结束遍历后的输出",self.atr_list)

  def sample_group(self, product, qty):
      for j in ['a','b','c','d','e','f',]:
        self.atrs[j]= qty/1317
      self.atr_list[product] = self.atrs
      print("在遍历中逐个水果输出结果",product, self.atrs)
      
if __name__ == "__main__":
  a=Backtest(10)
  a.run_testing()

在方法sample_group中每次输出的self.atrs是这样的:

img

但在run_testing 方法中输出的结果却是这样的:

img

在这段代码中,同一个变量输出结果不同的原因是因为在sample_group函数中,将一个字典self.atrs赋值给了另一个字典self.atr_list[product]。在循环迭代过程中,每次对self.atrs进行修改时,实际上修改的是同一个字典对象的值。由于self.atr_list[product]实际上是指向同一个字典对象的引用,因此在循环结束后,self.atr_list中保存的是最后一次循环中self.atrs字典的值。

如果要每次将self.atrs字典的副本保存到self.atr_list[product]中,可以使用copy方法:

self.atr_list[product] = self.atrs.copy()

这样每次将self.atrs的副本保存到self.atr_list[product]中,就不会出现同一个变量输出结果不同的情况了。

有用望采纳。

在这段代码中,第二个输出的结果不符合预期是因为字典 self.atrs 是在 sample_group 函数中被多次修改的,而在第二个输出语句中, self.atr_list[product] 的值是指向 self.atrs 的引用,因此最终的结果会受到 sample_group 函数中所有修改的影响。
要获得每一组的正确数值,可以将 self.atrs 的定义从 init 函数中移到 sample_group 函数内部,这样每次遍历 product 时,都会创建一个新的空字典 self.atrs,并向其中添加新的键值对,而不会对之前的结果造成影响。修改后的代码如下:

class Backtest:
  def __init__(self, n):
    self.n = n
    self.atr_list = {}

  def run_testing(self):
      for product in ['apple', 'orange', 'banana', 'lemon']:
        self.sample_group(product, self.n)
        self.n += 1
      print("在结束遍历后的输出", self.atr_list)

  def sample_group(self, product, qty):
      self.atrs = {}
      for j in ['a', 'b', 'c', 'd', 'e', 'f']:
        self.atrs[j] = qty/1317
      self.atr_list[product] = self.atrs
      print("在遍历中逐个水果输出结果", product, self.atrs)

if __name__ == "__main__":
  a = Backtest(10)
  a.run_testing()

在这个修改后的代码中,每个 sample_group 函数的执行都会创建一个新的空字典 self.atrs,然后在循环中向其中添加新的键值对,最后将其赋值给 self.atr_list[product],这样就能得到正确的结果。