This article is published in chapter 7 of the Python Dark Magic Manual v3.0


The dictionary is one of the basic data structures in Python. The dictionary is very simple to use, but even with such a data structure, there are still many people who are “not used to it”.

You may not think so, but I’m sure you’ll share my prejudice against native dictionaries after reading this article.

Let me give you a simple example

When you want to access a key in a dictionary, you need to use dictionary-specific access, which requires you to type a pair of brackets and a pair of quotes

>>> profile = dict(name="iswbm")
>>> profile
{'name': 'iswbm'}
>>> profile["name"]
'iswbm'
Copy the code

Are you starting to feel like the last straw?

It would be nice if you could use. To access the key as if you were calling an object property, saving a lot of extra keystrokes, like this

>>> profile.name
'iswbm'
Copy the code

Yes, today’s post is to share a dark magic library called Munch that you can use directly to access and manipulate dictionaries.

1. Installation method

Run the following command to install it

$ python -m pip install munch
Copy the code

2. Simple example

Munch has a munch class that inherits from the native dictionary and can be verified using isinstance

>>> from munch import Munch
>>> profile = Munch()
>>> isinstance(profile, dict)
True
>>>
Copy the code

Profile. name and profile[‘name’] are equivalent

>>> profile.name = "iswbm"
>>> profile.age = 18
>>> profile
Munch({'name': 'iswbm'.'age': 18}) > > >>>> profile.name
'iswbm'
>>> profile["name"]
'iswbm'
Copy the code

3. Compatible with all operations of dictionaries

Munch inherits from dict, and dict operations also apply to Munch objects

The first is: add, delete, change and check

# Add elements
>>> profile["gender"] = "male"
>>> profile
Munch({'name': 'iswbm'.'age': 18.'gender': 'male'})

# modify element
>>> profile["gender"] = "female"
>>> profile
Munch({'name': 'iswbm'.'age': 18.'gender': 'female'})

# delete element
>>> profile.pop("gender")
'female'
>>> profile
Munch({'name': 'iswbm'.'age': 18}) > > >>>> del profile["age"]
>>> profile
Munch({'name': 'iswbm'})
Copy the code

Again: some common methods

>>> profile.keys()
dict_keys(['name') > > >>>> profile.values()
dict_values(['iswbm') > > >>>> profile.get('name')
'iswbm'
>>> profile.setdefault('gender'.'male')
'male'
>>> profile
Munch({'name': 'iswbm'.'gender': 'male'})
Copy the code

4. Return the default value

KeyError is reported when accessing a key that does not exist in the dictionary

>>> profile = {}
>>> profile["name"]
Traceback (most recent call last):
  File "<stdin>", line 1.in <module>
KeyError: 'name'
Copy the code

In this case, we usually use get to get around it

>>> profile = {}
>>> profile.get("name"."undefined")
'undefined'
Copy the code

Of course you can still do this with Munch, but there’s a better way to do it: use DefaultMunch, which will give you a preset default value when you access a key that doesn’t exist

>>> from munch import DefaultMunch
>>> profile = DefaultMunch("undefined", {"name": "iswbm"})
>>> profile
DefaultMunch('undefined', {'name': 'iswbm'})
>>> profile.age
'undefined'
>>> profile
DefaultMunch('undefined', {'name': 'iswbm'})
Copy the code

5. The factory function automatically creates the key

Using DefaultMunch above only returns a default value if you access a nonexistent key, but this behavior does not modify anything about the original munch object.

If you want to access a key that doesn’t exist, it automatically triggers a new key to munch that you want to access and sets a default value for it, try DefaultFactoryMunch passing in a factory function.

>>> from munch import DefaultFactoryMunch
>>> profile = DefaultFactoryMunch(list, name='iswbm')
>>> profile
DefaultFactoryMunch(list, {'name': 'iswbm'}) > > >>>> profile.brothers
[]
>>> profile
DefaultFactoryMunch(list, {'name': 'iswbm'.'brothers': []})
Copy the code

6. Serialization support

Munch supports serialization of string objects to JSON or YAML formats

Converted to JSON

>>> from munch import Munch
>>> munch_obj = Munch(foo=Munch(lol=True), bar=100, msg='hello') > > >>>> import json
>>> json.dumps(munch_obj)
'{"foo": {"lol": true}, "bar": 100, "msg": "hello"}'
Copy the code

Convert YAML

>>> from munch import Munch
>>> munch_obj = Munch(foo=Munch(lol=True), bar=100, msg='hello')
>>> import yaml
>>> yaml.dump(munch_obj)
'! munch.Munch\nbar: 100\nfoo: ! munch.Munch\n lol: true\nmsg: hello\n'
>>>
>>> print(yaml.dump(munch_obj)) ! munch.Munch bar:100foo: ! munch.Munch lol: true msg: hello >>>Copy the code

Safe_dump is recommended. munch.Munch

>>> print(yaml.safe_dump(munch_obj))
bar: 100
foo:
  lol: true
msg: hello
Copy the code

7. Talk about limitations

That’s all for munch. Further encapsulation of Munch makes data access and manipulation more Pythonic, and replacing native dictionaries should not be a problem in most scenarios.

Admittedly, munch doesn’t work as well as the native dictionary in some cases, like when I think the key in the dictionary is “1.2”.

>>> dict_obj = {"1.2": "hello"}
>>> dict_obj["1.2"]
'hello'
Copy the code

Switch to Munch and you will find that you cannot pass in a key of 1.2 when initializing a Munch object

>>> from munch import Munch
>>> dict_obj = Munch(1.2="hello")
  File "<stdin>", line 1
    dict_obj = Munch(1.2="hello")
                     ^
SyntaxError: expression cannot contain assignment, perhaps you meant "= ="?
Copy the code

Even if you add this key-value in a native dictionary, it won’t work at all. To obtain the value corresponding to 1.2.

>>> from munch import Munch
>>> dict_obj = Munch()
>>> dict_obj["1.2"] ="hello"
>>> dict_obj
Munch({'1.2': 'hello'})
>>> dict_obj1.2.
  File "<stdin>", line 1
    dict_obj1.2.
            ^
SyntaxError: invalid syntax
Copy the code

Because of this, native dictionaries are still irreplaceable.

This is the last article in the Python Handbook of Dark Magic v3.0, which has been completed in PDF.

Release V3.0 · ISWBM/Magic-Python

Original is not easy, if the article is useful to you, but also ask you to give me a praise, grateful!