【问题标题】:Custom class using nested dictionary Python使用嵌套字典 Python 的自定义类
【发布时间】:2019-09-17 01:03:22
【问题描述】:

我在使用相同的键在嵌套字典中添加值时遇到问题,并且值始终显示相同的值,事实是,我想更新键相同的值事件。该算法是人工鱼群算法的基础

# example >> fish_template = {0:{'weight':3.1,'visual':2,'step':1},1:'weight':3,'visual':4,'step':2}}

fish = {}
fish_value = {}
weight = [3.1, 3, 4.1, 10]
visual = [2, 4, 10, 3]
step = [1, 2, 5, 1.5]

len_fish = 4

for i in range(0,len_fish):
  for w, v, s in zip(weight, visual, step):
     fish_value["weight"] = w
     fish_value["visual"] = v
     fish_value["step"] = s
     fish[i] = fish_value

  print("show fish",fish)

我希望结果类似于fish_template,但事实并非如此。 'weight'、'visual'、'step' 键的值与 0、1、2 和 3 的值始终相同。有解决方案吗?

【问题讨论】:

  • 因为别名; fish[i] = fish_value 行是不好的做法,fish_value 会被覆盖。但实际上,您可以通过 dict 理解来避免循环。无论如何,更好的编码实践是声明你自己的 Fish 具有权重、视觉、步骤成员的类。
  • @smci,好的,所以最好创建类或对象来获取每个循环的值,感谢您的建议

标签: python-3.x list dictionary optimization swarm


【解决方案1】:

由于别名fish[i] = fish_value 行是不好的做法,fish_value 每次循环时都会被覆盖;然后fish[i] = fish_value 只是将浅拷贝分配给fish[i],这不是您想要的。 但实际上你可以通过 dict 理解避免循环

无论如何,更好的编码实践是用成员weight, visual, step 声明你自己的Fish,如下所示。注意方法:

  • 我们使用 zip() 函数将单独的 w,v,s 列表组合成一个 tuple-of-list。
  • 然后语法*wvs 将每个元组解包为三个单独的值('weight'、'visual'、'step')。这称为元组解包,它可以避免您需要另一个循环或索引。
  • 自定义 __repr__() 方法(带有可选的 ASCII 艺术)使每个对象都易于用户阅读。 (严格来说,我们应该覆盖 __str__ 而不是 __repr__,但这可行)

代码:

class Fish():
    def __init__(self, weight=None, visual=None, step=None):
        self.weight = weight
        self.visual = visual
        self.step = step
    def __repr__(self):
        """Custom fishy __repr__ method, with ASCII picture"""
        return f'<º)))< ? [ Weight: {self.weight}, visual: {self.visual}, step: {self.step} ]'
    # define whatever other methods you need on 'Fish' object...

# Now create several Fish'es...
swarm = [ Fish(*wvs) for wvs in zip([3.1, 3, 4.1, 10], [2, 4, 10, 3], [1, 2, 5, 1.5]) ]
# zip() function combines the lists into a tuple-of-list. `*wvs` unpacks each tuple into three separate values ('weight', 'visual', 'step')

# See what we created...
>>> swarm
[<º)))< ? [ Weight: 3.1, visual: 2, step: 1 ], <º)))< ? [ Weight: 3, visual: 4, step: 2 ], <º)))< ? [ Weight: 4.1, visual: 10, step: 5 ], <º)))< ? [ Weight: 10, visual: 3, step: 1.5 ]]

# ... or for prettier output...
>>> for f in swarm: print(f)

<º)))< ? [ Weight: 3.1, visual: 2, step: 1 ]
<º)))< ? [ Weight: 3, visual: 4, step: 2 ]
<º)))< ? [ Weight: 4.1, visual: 10, step: 5 ]
<º)))< ? [ Weight: 10, visual: 3, step: 1.5 ]

【讨论】:

  • 严格的类应该覆盖他们的__str__而不是__repr__,但是除非你想pickle你的Fish...;-)
  • 当然可以。当你到达15 reputation, you can upvote answers you found helpful。到那时,快乐蜂拥而至……
  • 你喜欢自定义的鱼腥味__repr__ 方法吗?
  • 我已经根据您的答案之前的第一个答案创建了自己的自定义鱼。抱歉,但您的回答让我对新代码有另一种看法,谢谢
【解决方案2】:

问题在于fish[i],您只需创建一个具有相同元素的dictfish_value。 Python 不会为相同的变量名生成新内存,因此所有 dict 键都指向相同的 value=fish_value,它会被覆盖,并且所有 dict 值都采用fish_value 的最后状态。为了克服这个问题,您可以执行以下操作:

fish   = {}
weight = [3.1, 3, 4.1, 10]
visual = [2, 4, 10, 3]
step   = [1, 2, 5, 1.5]

len_fish = 4

for i in range(0, len_fish):
     fish[i]= {"weight": weight[i], "visual": visual[i], "step": step[i]}

print("show fish", fish)

正如@Error 提到的,for 循环可以用这个单线代替:

fish = dict((i, {"weight": weight[i], "visual": visual[i], "step": step[i]}) for i in range(len_fish))

【讨论】:

  • 你可以用字典理解把它排成一行。
  • @Error-SyntacticalRemorse:我在下面展示了单行理解。使用自定义类,但这不是必需的。
【解决方案3】:

不确定我是否完全理解您在此处尝试执行的操作,但问题是您的内部 for 循环的最后一行。您在主循环中循环i,然后内部循环设置fish[i] 多次。结果,您的所有 fish_value 看起来都相同。

【讨论】:

  • 是的,我已经尝试在里面打印值显示出来,但是当我从最后一个循环中得到最后一个值不是添加后的全部值
猜你喜欢
  • 2019-04-21
  • 2022-07-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-09-20
  • 1970-01-01
  • 2018-05-31
相关资源
最近更新 更多