Странное поведение словаря, созданного из fromkeys
коллеги! Просветите меня, пожалуйста, за странное поведение аппенда в ключ словаря, созданного из fromkeys:
def hash_as_key(obj):
x = {}.fromkeys([hash(i) for i in obj], [])
[x[hash(j)].append(j) for j in obj]
return {k:v if len(v) != 1 else v[0] for k, v in x.items()}
print(hash_as_key([1, 2, 3, 4, 5, 5]))
Требуемый вывод: {1: 1, 2: 2, 3: 3, 4: 4, 5: [5, 5]}
Фактический вывод: {1: [1, 2, 3, 4, 5, 5], 2: [1, 2, 3, 4, 5, 5], 3: [1, 2, 3, 4, 5, 5], 4: [1, 2, 3, 4, 5, 5], 5: [1, 2, 3, 4, 5, 5]}
Аппендится весь список, вместо конкретного значения из списка. При этом, если создавать словарь через defaultdict - все работает как требуется.
Ответы (1 шт):
Совершенно нормальное поведение, строго по докстрингу:
Signature: dict.fromkeys(iterable, value=None, /)
Docstring: Create a new dictionary with keys from iterable and values set to value.
Все значения словаря устанавливаются указанным вами значением. А значение у вас - один конкретный пустой список. В результате, все значения этого словаря указывают на один и тот же список.
Хотите задать в качестве значений разные списки - используйте, например, словарное сокращение (или как это правильно называется):
x = {hash(i):[] for i in obj}
Ну или defaultdict(list), тогда списки тоже будут разные, да.
Да, и зачем вы, собственно, используете hash в явном виде я тоже не понял. Плюсов тут никаких, но есть риск нарваться на коллизию хэшэй. Словарь и так сам под капотом будет использовать hash, а в случае коллизии - явное сравнение объектов, чего у вас и нет. Например, можете глянуть, чему внезапно равен hash(-1), ну и другие интересные случаи могут быть.