Munch – вседозволенный объект

КДПВ

Привет. Хочу познакомить вас библиотекой Munch, которая является форком более старой библиотеки Bunch. Рассмотрим суть проблемы, которую она решает. Задать атрибуты объекта, не описывая их по одному в конструкторе. Легче понять на примере:

>>> f = object()
>>> f.x = 10
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'object' object has no attribute 'x'

Видно, что object нам не поможет. Но в Python 3 можно сделать пустой класс, это не вызовет ошибки:

class Bunch: ...

foo = Bunch()
foo.x = 10
foo.y = 20

И в принципе этого может быть достаточно. Но иногда хочется больше. В моей практике возникла задача, когда нужно было имитировать классы из сторонней библиотеки. Использовать сами эти классы было громоздко и неудобно, потому что там было много лишнего кода, и нужно было придумать решение, как от него избавиться, чтобы избежать ошибок и побочных эффектов. Пришла на помощь библиотека с которая к слову имеет кучу мелких удобных возможностей.

Установка:

pip install munch

Объект Munch – это наследник словаря dict, с ним можно работать как со словарем, но можно также произвольно работать с его атрибутами:

from munch import *

# пустой
b = Munch()

# задаем атрибуты
b.hello = 'world'
print(b.hello)  # world

b['hello'] += "!"
print(b.hello)  # world!

print(b.hello is b['hello'])  # True

# атрибут может быть тоже Munch
b.bar = Munch()
b.bar.baz = 100
print(b.bar.baz)  # 100

Т.е. мы может обращаться к данным как через точку (как атрибут), так и через квадратные скобки (как с обычным словарем) – это будут одни и те же данные, при условии равных имен.

Очень удобная фишка – создание Munch через конструктор, просто перечисляем ключевые слова, и они станут атрибутами:

# задать через конструктор
c = Munch(x=10, y=20, z=30)
print(c.x, c.y, c.z)  # 10 20 30

С Munch можно работать, как с обычным dict, например:

c = Munch(x=10, y=20, z=30)
print(list(c.keys()))  # список атрибутов

c.update({
    'w': 10,
    'name': 'ganesh'
})
print(c)  # Munch({'x': 10, 'y': 20, 'z': 30, 'w': 10, 'name': 'ganesh'})

print([(k, v) for k, v in c.items()])
# [('x', 10), ('y', 20), ('z', 30), ('w', 10), ('name', 'ganesh')]

Удобно сеарилизовтать такие объекты:

# JSON

b = Munch(foo=Munch(lol=True), hello=42, ponies='are pretty!')
import json
print(json.dumps(b))
#  {"foo": {"lol": true}, "hello": 42, "ponies": "are pretty!"}

# YAML - если есть.
import yaml
print(yaml.dump(b))  # или
print(yaml.safe_dump(b))

Замечание

В библиотеку collections Python 3 уже включен объект UserDict со схожей функциональностью:

from collections import UserDict

a = UserDict()
a.p = 10

Специально для канала @pyway. Подписывайтесь на мой канал в Телеграм @pyway 👈 

Добавить комментарий