Python dict accessible by dot.
Project description
dictdot
Python dict accessible by dot, similar to how it's done with an object in Javascript.
It provides the same nature of a dict, plus facilities in notation and a find functionality that helps in the data exploration process. Particularly useful when dealing with a large JSON that you don't know much about.
It's implemented by overriding some builtin methods of regular Python dict, then it has no impact in performance or memory footprint. Nevertheless, for productive code it's always recommended to use the native Python dictionaries.
Usage
Minimal example
from dictdot import dictdot
d = dictdot()
# Get and set items either by dot or regular notation.
d["foo"] = 1
d.bar = 1
assert d.foo == d["bar"]
# Nested dicts are also converted to dictdot.
d.bar = [{"baz": 1}]
assert type(d.bar[0]) is dictdot
# Find elements by key or value.
assert [".foo", ".bar[0].baz"] == list(dictdot.find(d, check_value=1))
Performance analysis
Now let's see a more illustrative use case. We'll be using this ~25MB JSON file. If you have curl installed in your terminal, you can download it as follows:
curl -JO https://raw.githubusercontent.com/json-iterator/test-data/master/large-file.json
The following Python code can be run as it is if you have dictdot installed and large-file.json in the current directory. It will load the file in memory, then convert it to dictdot, and perform some find tasks on it, measuring the time in each step. I share the time for each step running it in my 2018 laptop (2.6GHz CPU)):
import json
import time
from dictdot import dictdot
def get_time(old_t=None):
new_t = time.time()
if old_t:
print(f"Time: {new_t - old_t:.2f} sec\n")
return new_t
t = get_time()
print("Load data from file.")
with open("large-file.json") as f:
data = json.load(f)
t = get_time(t)
# Time: 0.36 sec
print("Convert to `dictdot`.")
data = [dictdot(d) for d in data]
t = get_time(t)
# Time: 4.67 sec
print("List all keys.")
ks = list(dictdot.find(data))
print(f"{len(ks)} keys found.")
t = get_time(t)
# 626243 keys found.
# Time: 5.53 sec
print("Find values by function.")
vs = list(dictdot.find(data, check_value=lambda v: type(v) is str and " dict " in v))
print(f"{len(vs)} values found.")
t = get_time(t)
# 2 values found.
# Time: 0.62 sec
print("Convert back to dict.")
dic = [d.as_dict() for d in data]
t = get_time(t)
# Time: 0.38 sec
Finding values
In the example above, the variable vs contains paths that represent items within data. These items match the condition of being strings, and containing the substring " dict " (with trailing spaces). Let's check them:
vs[0]
# '[169].payload.comment.body'
data[169].payload.comment.body
# "What about making the combined dict a local variable, like...
Comparing the notation
Which prefer?
vs[1]
# '[1275].payload.commits[0].message'
assert data[1275].payload.commits[0].message is \
data[1275]["payload"]["commits"][0]["message"]
Feature summary
-
Can initialize
dictdotthe same way asdict:a = ["foo", "bar", "baz"] b = range(3) d = dictdot(zip(a, b))
-
Access items by dot notation, or as a
dict:assert d.foo < d["bar"] < d.get("baz")
-
Also when setting an item:
d.bar = { "fee": 1, "boo": None, }
-
Convert to regular
dict:d2 = d.as_dict() assert d == d2 assert type(d2) is dict
-
Function to find keys and values nested in the dict structure:
# Find every key equal to "foo". assert list(dictdot.find(d, check_key="foo")) == [".foo"] # Find every value that bool-evaluates to False. assert list(dictdot.find(d, check_value=lambda v: not v)) == [".foo", ".bar.boo"] # Both key and value must evaluate to True. assert list(dictdot.find(d, check_key="bar", check_value=1)) == []
See the tests in the source code for more details about the behavior and usage.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distributions
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file dictdot-1.5.1-py3-none-any.whl.
File metadata
- Download URL: dictdot-1.5.1-py3-none-any.whl
- Upload date:
- Size: 5.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/4.0.2 CPython/3.9.16
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e787166b3f58667a0ef8d7ee8f06340c936efda1d256d0a6b5e4a679cddd5190
|
|
| MD5 |
6505498b14e285708a34d64821bf669f
|
|
| BLAKE2b-256 |
87105cbc343025a94969b51e2273d0023677125649383128a140edd5369247c7
|