Python 更新字典并在列表末尾附加循环

Python updating dictionary and appending at the end of list with loop

是否有一种正确的方法来更新字典并将该字典附加到列表中而不会导致重复。这是为了与 netmiko 一起使用,我的目标是让它有点动态和灵活,尤其是命名方案。

#!/usr/bin/python
import re

hosts_info = []
host = {
    'device_type': 'cisco_ios',
    'ip': 'co-acc-sw',
    'username': 'cisco',
    'password': 'notapassword',
    'secret': 'mrsecret'
}

for x in range(0, 4):
    if x < 2:
        host.update({"ip": "core-switch" + str(x)})
    elif x > 2:
        host.update({"ip": "access-switch" + str(x - 1)})
    hosts_info.append(host)
print(hosts_info)

当前输出为:

[{'device_type': 'cisco_ios', 'ip': 'access-switch2', 'username': 'cisco', 'password': 'notapassword', 'secret': 'mrsecret'}, 
{'device_type': 'cisco_ios', 'ip': 'access-switch2', 'username': 'cisco', 'password': 'notapassword', 'secret': 'mrsecret'}, 
{'device_type': 'cisco_ios', 'ip': 'access-switch2', 'username': 'cisco', 'password': 'notapassword', 'secret': 'mrsecret'}, 
{'device_type': 'cisco_ios', 'ip': 'access-switch2', 'username': 'cisco', 'password': 'notapassword', 'secret': 'mrsecret'}]

我试图让它看起来像这样:

[{'device_type': 'cisco_ios', 'ip': 'core-switch1', 'username': 'cisco', 'password': 'notapassword', 'secret': 'mrsecret'}, 
{'device_type': 'cisco_ios', 'ip': 'core-switch2', 'username': 'cisco', 'password': 'notapassword', 'secret': 'mrsecret'}, 
{'device_type': 'cisco_ios', 'ip': 'access-switch1', 'username': 'cisco', 'password': 'notapassword', 'secret': 'mrsecret'}, 
{'device_type': 'cisco_ios', 'ip': 'access-switch2', 'username': 'cisco', 'password': 'notapassword', 'secret': 'mrsecret'}]

如果我创建单独的字典并将它们添加到单独的 if 语句中,我可以让它工作,只是想知道是否有更好的方法来做到这一点?谢谢。

列表中的每一项都需要是自己的字典;您现有的代码只有一个字典 (host),它会不断更新(覆盖以前的更新)并构建一个列表,其中包含对同一个字典的四个引用。

创建一个现有字典的部分副本的新字典的一种简单方法是使用 **olddict:

进行字典理解
for x in range(0, 4):
    if x < 2:
        hosts_info.append({**host, "ip": "core-switch" + str(x)})
    elif x > 2:
        hosts_info.append({**host, "ip": "access-switch" + str(x - 1)})
    else:
        hosts_info.append({**host})

这更多是您的原始代码试图做的事情(减去指针错误),但实际上仍然没有产生您想要的输出,因为数学错误。

我认为使数学工作的方法更像是:

hosts_info = [{
    **host, "ip": f"core-switch{x+1}" if x < 2 else f"access-switch{x-1}"
} for x in range(4)]

或者,与其尝试巧妙地设计一个循环,通过计算范围内不同 int 值的偏移量来生成您想要的不同字符串值,您可以只执行一个嵌套循环,在该循环中迭代实际值想要:

hosts_info = [{
    **host, "ip": f"{switch}-switch{x}"
} for switch in ("core", "access") for x in (1, 2)]

到目前为止,这比 IMO 更具可读性,因为输出非常直接且明显地对应于代码,而棘手的数学使得很难弄清楚原始代码甚至试图产生什么(而且它很重要做正确事情的数学)。

快速解决方法是:

for x in range(0, 4):
    h = dict(host)
    if x < 2:
        h.update({"ip": "core-switch" + str(x + 1)})
    elif x >= 2:
        h.update({"ip": "access-switch" + str(x - 1)})
    hosts_info.append(h)

因为您需要明确复制字典。不过我建议也看看 Samwise 的回答。