What is a mapping in Python?
mappingdefinition in Python Terminology.
Here we have an INI file, called pytest.ini
:
[pytest]
norecursedirs = node_modules
addopts = --ignore=src
log_cli = True
We can parse this INI file using the ConfigParser
class from Python's configparser
module:
>>> from configparser import ConfigParser
>>> config = ConfigParser()
>>> config.read('pytest.ini')
['pytest.ini']
ConfigParser
objects act like dictionaries.
They aren't dictionaries, but they act like a dictionary.
Just like a dictionary, we can use square brackets ([
...]
) with a ConfigParser
object.
>>> section = config['pytest']
The "keys" in a ConfigParser
object are section names.
Looking up a section by its name gives us back a Section
object:
>>> section
<Section: pytest>
This Section
object also acts like a dictionary.
We can use square brackets with a Section
: if we give it a key we'll get back the value for that key within our section:
>>> section['log_cli']
'True'
We can also use the built-in len
function to get the number of key-value pairs within a section (just like a dictionary):
>>> len(section)
3
We can even use methods that you'd expect to find in a dictionary, like the keys
method, the values
method, and the items
method:
>>> for name, value in section.items():
... print(f"{name} = {value}")
...
norecursedirs = node_modules
addopts = --ignore=src
log_cli = True
In Python, we use the term mapping to refer to objects that act like a dictionary.
Our ConfigParser
object and each Section
object within it are mappings.
These ConfigParser
and Section
objects aren't just mappings, they're mutable mappings, meaning just like the built-in dict
type, we can change their contents.
We could add a new key-value pair to a section:
>>> section['log_cli_level'] = 'INFO'
Or we could update the value for an existing key:
>>> section['log_cli'] = 'False'
We could also delete items from a section:
>>> del section['log_cli_level']
These objects are mutable, just as dictionaries in Python are mutable.
Not all mappings are mutable.
One example of an immutable mapping is types.MappingProxyType
.
>>> from types import MappingProxyType
The MappingProxyType
class creates objects that wrap around an existing mapping and proxy operations to them.
For example we could make a MappingProxyType
object that wraps around our Section
object:
>>> proxy = MappingProxyType(section)
>>> proxy
mappingproxy(<Section: pytest>)
This proxy
object will proxy operations to our section mapping.
So when we look up a key within it, it'll do the same thing as if we look up the key in our Section
object:
>>> proxy['log_cli']
'False'
This proxy
object is an immutable mapping object.
So while we can perform dictionary-like operations that don't mutate it, we can't perform any operations that would mutate it.
We could use its values
method, for example:
>>> for value in proxy.values():
... print(value)
...
node_modules
--ignore=src
False
INFO
Or we could use the built-in len
function on it:
>>> len(proxy)
4
Or we could call its get
method:
>>> proxy.get("pytest_classes", "Test*")
'Test*'
But we can't assign to its keys:
>>> proxy['log_cli'] = 'True'
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'mappingproxy' object does not support item assignment
And we also can't delete key-value pairs from it:
>>> del proxy['log_cli']
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'mappingproxy' object does not support item deletion
Dictionaries are mutable mappings, but the word mapping doesn't imply mutability.
This object can't be mutated, but it is still a mapping. It's just an immutable mapping.
Mappings are used throughout the Python Standard Library and third-party libraries.
Mapping is just a generic word for a dictionary-like object. If an object can be subscripted (with square brackets) it's probably a mapping.
Mappings are typically expected to have a length, a get
method, a values
method, an items
method, and a keys
method, just like a dictionary would.
If an object can be mutated (just like dictionaries can) then it's a mutable mapping.
Need to fill-in gaps in your Python skills?
Sign up for my Python newsletter where I share one of my favorite Python tips every week.
Sign in to your Python Morsels account to track your progress.
Don't have an account yet? Sign up here.