自定义 class 使用嵌套字典 Python
Custom class using nested dictionary Python
我在使用相同的键在嵌套字典中添加值时遇到问题,并且该值始终显示相同的值,事实是,我想在键相同的情况下更新值事件。该算法是人工鱼群算法的基础
# 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 相同。有解决方案吗?
不确定我是否完全理解您在这里尝试做什么,但问题出在您内部 for 循环的最后一行。您在主循环中遍历 i
,然后内部循环多次设置 fish[i]
。结果,您的所有 fish_value 看起来都一样。
问题出在 fish[i]
,您只是用相同的元素创建了一个 dict
:fish_value
。 Python 不会为相同的变量名生成新的内存,所以你所有的字典键都指向相同的值=fish_value
,它被覆盖并且你所有的字典值都采用 [=14 的最后状态=].要克服这个问题,您可以执行以下操作:
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))
因为别名; fish[i] = fish_value
行是不好的做法,每次循环时 fish_value
都会被覆盖;然后 fish[i] = fish_value
只是将浅表副本分配给 fish[i]
,这不是您想要的。
但实际上你可以通过字典理解来避免循环。
无论如何,更好的编码做法是 声明您自己的 Fish
class 和成员 weight, visual, step
,如下所示。注意如何:
- 我们使用
zip()
函数将单独的 w,v,s
列表组合成一个列表元组。
- 然后语法
*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 ]
我在使用相同的键在嵌套字典中添加值时遇到问题,并且该值始终显示相同的值,事实是,我想在键相同的情况下更新值事件。该算法是人工鱼群算法的基础
# 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 相同。有解决方案吗?
不确定我是否完全理解您在这里尝试做什么,但问题出在您内部 for 循环的最后一行。您在主循环中遍历 i
,然后内部循环多次设置 fish[i]
。结果,您的所有 fish_value 看起来都一样。
问题出在 fish[i]
,您只是用相同的元素创建了一个 dict
:fish_value
。 Python 不会为相同的变量名生成新的内存,所以你所有的字典键都指向相同的值=fish_value
,它被覆盖并且你所有的字典值都采用 [=14 的最后状态=].要克服这个问题,您可以执行以下操作:
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))
因为别名; fish[i] = fish_value
行是不好的做法,每次循环时 fish_value
都会被覆盖;然后 fish[i] = fish_value
只是将浅表副本分配给 fish[i]
,这不是您想要的。
但实际上你可以通过字典理解来避免循环。
无论如何,更好的编码做法是 声明您自己的 Fish
class 和成员 weight, visual, step
,如下所示。注意如何:
- 我们使用
zip()
函数将单独的w,v,s
列表组合成一个列表元组。 - 然后语法
*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 ]