Pull to refresh

"Складываем" хеши в Python ("синтаксический сахар")

Reading time 2 min
Views 4.7K
Понятно, что собственно сложения ассоциативных массивов (они же хеши, dict-ы и т.п. в разных языках) не существует, т.к. совершенно неочевидно, что оно должно давать. Но иногда удобно иметь простую легкочитаемую операцию, которая бы легко и просто объединяла хеши. Особенно это удобно когда есть ряд хешей и вам нужно оттуда взять несколько ключей с разным приоритетом. Если нет значения в первом, то проверяем второй, если нет и там, то третий, и т.п.
У вас есть 4 хеша global_config, local_config, db_row, user_info
Чуть ниже хабраката я покажу как жуткую конструкцию из 4 строк
values = global_config.copy()
values.update(local_config)
values.update(db_row)
values.update(user_info)
Записать в одну
values = global_config + local_config + db_row + user_info



Понятно, что «в лоб» это не выйдет. Хеши такую операцию не знают. Поэтому мы создадим свой класс на основе базового dict, который можно будет складывать:
class AddableDict(dict):
   def __add__(self, x):
      s = AddableDict(self)
      s.update(x)
      return s


* This source code was highlighted with Source Code Highlighter.


Обратите внимание как легко это делается — нам нужно всего лишь добавить метод, который будет вызываться оператором "+".

Класс во всем ведет себя подобно хешу: так же создается, добавляются значения ключей и т.п.:
>>> q=AddableDict(a=2, b=5)
>>> q
{'a': 2, 'b': 5}
>>> w=AddableDict({'a':3})
>>> w
{'a': 3}
>>> q['a']=444
>>> q
{'a': 444, 'b': 5}
>>> q['g']='sdf'
>>> q
{'a': 444, 'b': 5, 'g': 'sdf'}
>>>

* This source code was highlighted with Source Code Highlighter.

С той лишь разницей, что их теперь можно складывать. Если возникает дублирование ключей, то значения правого заменяют соответсвующий значения левого — все как в методе .update().

>>> q+w
{'a': 3, 'b': 5}
* This source code was highlighted with Source Code Highlighter.


Где в программе брать такие хеши? Не переписывать же все заново! Тем более есть масса стандартных функций, которые и не знают про наши новые возможности.
К счастью, прболема решается легко. Любой хеш можно быстро превратить в такой:
>>> w=AddableDict({'a':3})
>>> w
{'a': 3}

* This source code was highlighted with Source Code Highlighter.


Где можно использовать?
Везде, где хотите сократить запись и улучшить читаемость программы.
В текущем проекте мне часто требуется выбирать информацию из нескольких источников с разным приоритетом, например, значение из БД, значение по умолчанию для данного класса, из настроек проекта и т.п.
global_config = {'a':1, 'b':4}
local_config = {'a':7, 'c':1}
db_row = {'a':10}
user_info = {'c':0}

values = global_config.copy()
values.update(local_config)
values.update(db_row)
values.update(user_info)
  ИЛИ
values = global_config + local_config + db_row + user_info


* This source code was highlighted with Source Code Highlighter.


Данная статья не претендует на фундаментальность, здесь описан способ упрощения записи для удобства чтения — «синтаксический сахар».

Спасибо за комментарии!
Tags:
Hubs:
+24
Comments 20
Comments Comments 20

Articles