1
>>> servers = ["srv1.usa", "srv1.lnd"]
>>> proxies = ["proxy1.usa", "proxy1.lnd"]
>>> proxy_map = {}.fromkeys(servers, {}.fromkeys(proxies, {}))
>>> print proxy_map
{'srv1.lnd': {'proxy1.lnd': {}, 'proxy1.usa': {}}, 'srv1.usa': {'proxy1.lnd': {}, 'proxy1.usa': {}}}
>>> proxy_map["srv1.lnd"]["proxy1.lnd"] = {"hosts": "host1.usa"}
>>> print proxy_map
{'srv1.lnd': {'proxy1.lnd': {'hosts': 'host1.usa'}, 'proxy1.usa': {}}, 'srv1.usa': {'proxy1.lnd': {'hosts': 'host1.usa'}, 'proxy1.usa': {}}}

That's my question, why python changed two dictionaries instead of one that I changed? Sorry, if this question is stupid, but I did not found answer for my case. Thank you!

  • The answers to the duplicate do not provide any good explations of _why_ this happens, which is what OP wants to know. – Håken Lid Jun 01 '16 at 19:00

2 Answers2

4

fromkeys is a trap. Don't use it.

When you use dict.fromkeys, all values of the resulting dict are the same object. Not just equal objects - they're the same object. If you do d = dict.fromkeys(keys, val), anything you do to d[key1] is visible through d[key2], because d[key1] and d[key2] are the same thing.

dict.fromkeys is usually only useful when the values are immutable. The rest of the time, you should use a dict comprehension to reevaluate the value expression for each key. For example,

{key: {} for key in keys}

instead of dict.fromkeys(keys, {}).

user2357112
  • 260,549
  • 28
  • 431
  • 505
0

The solutions is to use dictionary comprehension:

Instead of proxy_map = {}.fromkeys(servers, {}.fromkeys(proxies, {}))

use

proxy_map = {server : {proxy: {} for proxy in proxies} for server in servers}

Complete example:

>>> servers = ["srv1.usa", "srv1.lnd"]
>>> proxies = ["proxy1.usa", "proxy1.lnd"]
>>> proxy_map = {server : {proxy: {} for proxy in proxies} for server in servers}
>>> proxy_map
{'srv1.usa': {'proxy1.usa': {}, 'proxy1.lnd': {}}, 'srv1.lnd': {'proxy1.usa': {}, 'proxy1.lnd': {}}}
>>> proxy_map["srv1.lnd"]["proxy1.lnd"] = {"hosts": "host1.usa"}
>>> proxy_map
{'srv1.usa': {'proxy1.usa': {}, 'proxy1.lnd': {}}, 'srv1.lnd': {'proxy1.usa': {}, 'proxy1.lnd': {'hosts': 'host1.usa'}}}
Erich
  • 1,838
  • 16
  • 20