A Python dict subclass which tries to act like JavaScript objects, so you can use the dot-notation (d.foo) to access members of the object.
Project description
<h1>MyDict</h1>
<p>A <strong>Python</strong> <em>dict</em> subclass which tries to act like <strong>JavaScript</strong> objects, so you can use the <strong>dot notation</strong> (<em>d.foo</em>) to access members of the object. If the member doesn't exist yet then it's created when you assign a value to it. Brackets notation (<em>d['foo']</em>) is also possible.</p>
<h2>Installation</h2>
<pre><code>$ pip install mydict
</code></pre>
<h2>Examples</h2>
<p>Let's give it a try</p>
<pre><code>d = MyDict()
d.foo = 'bar'
print(d.foo)
# ==> 'bar'
</code></pre>
<p>If you try to get the value of a non-existing member then a <em>None</em> value is returned</p>
<pre><code>d = MyDict()
if d.foo is None:
print('"foo" does not exist yet!')
</code></pre>
<p>If that value is "complex" (a <em>dict</em> or another <em>MyDict</em> instance), then it's also <strong>recursively</strong> transformed into a <em>MyDict</em> object, so you can access it in the same way</p>
<pre><code>d = MyDict()
d.foo = {'bar': 'baz', 'lst': [{'a': 123}]}
print(d.foo.bar)
# ==> 'baz'
print(d.foo.bar)
# ==> 'baz'
print(d.foo.lst[0].a)
# ==> 123
</code></pre>
<p>Values in lists are accessed, as you expect, with the brackets notation (<em>d[0]</em>):</p>
<pre><code>d = MyDict()
d.foo = [1, 2, 3]
print(d.foo[2])
# ==> 3
</code></pre>
<p>We can instantiate it from a <em>dict</em> of any level of complexity</p>
<pre><code>d = MyDict({'foo': 'bar', 'baz': [1, 2, {'foo': 'bar', 'baz': 'Hello, world!'}}])
print(d.foo)
# ==> 'bar'
print(d.baz[0])
# ==> 1
print(d.baz[2].foo)
# ==> 'bar'
</code></pre>
<p>with keywords in the <em>constructor</em></p>
<pre><code>d = MyDict(a=1, b=2.2, c=[1, 2, 3], d=[{'x': 1, 'y': [100, 200, 300]}])
...
d.a == 1
d.b == 2.2
d.c[0] == 1
d.d[0].x == 1
d.d[0].y[1] == 200
</code></pre>
<p>or both</p>
<pre><code>d = MyDict({'foo': 'bar'}, baz=123)
...
d.foo == 'bar'
d.baz == 123
</code></pre>
<p>Please, take into account that keyword initialization has precedence over the <em>dict</em> (first parameter of the <em>constructor</em>)</p>
<pre><code>d = MyDict({'foo': 'bar'}, foo='BAR')
...
d.foo == 'BAR'
</code></pre>
<p>It's also possible to access members using a <em>path</em> with <strong>get</strong> or <em>brackets notation</em> (<em>d['...']</em>):</p>
<pre><code>d = MyDict(foo={'bar': 'baz'})
...
d['foo.bar'] == 'baz'
d.get('foo.bar') == 'baz'
</code></pre>
<p>But when those keys <em>with dots</em> exists in the tree they are accessed using the corresponding key</p>
<pre><code>d = MyDict({'foo.bar': 'baz'})
...
# 'foo.bar' is not interpreted as a path because the key exists
d['foo.bar'] = 'baz'
</code></pre>
<p>But there's a particular case, if a <em>dotted key</em> exists and match an existing <em>path</em>, then this ain't work properly, or work in a different way depending on the method of access used, to be correct</p>
<pre><code>d = MyDict({'foo': {'bar': 'baz'}, 'foo.bar': 'BAZ'})
...
d['foo.bar'] = 'BAZ' # the "dotted field" ('foo.bar') has precedence over the path
d.foo.bar = 'baz' # it's not possible to detect a "dotted key" using "dot notation"
</code></pre>
<p>Personally, I don't see this as a great issue because I generally avoid using dots in keys, like in the previous case</p>
<p>The tests passed successfully with <strong>Python 3.6</strong> and <strong>Python 2.7</strong> versions.</p>
<pre><code>$ pytest mydict -v
</code></pre>
<p>A <strong>Python</strong> <em>dict</em> subclass which tries to act like <strong>JavaScript</strong> objects, so you can use the <strong>dot notation</strong> (<em>d.foo</em>) to access members of the object. If the member doesn't exist yet then it's created when you assign a value to it. Brackets notation (<em>d['foo']</em>) is also possible.</p>
<h2>Installation</h2>
<pre><code>$ pip install mydict
</code></pre>
<h2>Examples</h2>
<p>Let's give it a try</p>
<pre><code>d = MyDict()
d.foo = 'bar'
print(d.foo)
# ==> 'bar'
</code></pre>
<p>If you try to get the value of a non-existing member then a <em>None</em> value is returned</p>
<pre><code>d = MyDict()
if d.foo is None:
print('"foo" does not exist yet!')
</code></pre>
<p>If that value is "complex" (a <em>dict</em> or another <em>MyDict</em> instance), then it's also <strong>recursively</strong> transformed into a <em>MyDict</em> object, so you can access it in the same way</p>
<pre><code>d = MyDict()
d.foo = {'bar': 'baz', 'lst': [{'a': 123}]}
print(d.foo.bar)
# ==> 'baz'
print(d.foo.bar)
# ==> 'baz'
print(d.foo.lst[0].a)
# ==> 123
</code></pre>
<p>Values in lists are accessed, as you expect, with the brackets notation (<em>d[0]</em>):</p>
<pre><code>d = MyDict()
d.foo = [1, 2, 3]
print(d.foo[2])
# ==> 3
</code></pre>
<p>We can instantiate it from a <em>dict</em> of any level of complexity</p>
<pre><code>d = MyDict({'foo': 'bar', 'baz': [1, 2, {'foo': 'bar', 'baz': 'Hello, world!'}}])
print(d.foo)
# ==> 'bar'
print(d.baz[0])
# ==> 1
print(d.baz[2].foo)
# ==> 'bar'
</code></pre>
<p>with keywords in the <em>constructor</em></p>
<pre><code>d = MyDict(a=1, b=2.2, c=[1, 2, 3], d=[{'x': 1, 'y': [100, 200, 300]}])
...
d.a == 1
d.b == 2.2
d.c[0] == 1
d.d[0].x == 1
d.d[0].y[1] == 200
</code></pre>
<p>or both</p>
<pre><code>d = MyDict({'foo': 'bar'}, baz=123)
...
d.foo == 'bar'
d.baz == 123
</code></pre>
<p>Please, take into account that keyword initialization has precedence over the <em>dict</em> (first parameter of the <em>constructor</em>)</p>
<pre><code>d = MyDict({'foo': 'bar'}, foo='BAR')
...
d.foo == 'BAR'
</code></pre>
<p>It's also possible to access members using a <em>path</em> with <strong>get</strong> or <em>brackets notation</em> (<em>d['...']</em>):</p>
<pre><code>d = MyDict(foo={'bar': 'baz'})
...
d['foo.bar'] == 'baz'
d.get('foo.bar') == 'baz'
</code></pre>
<p>But when those keys <em>with dots</em> exists in the tree they are accessed using the corresponding key</p>
<pre><code>d = MyDict({'foo.bar': 'baz'})
...
# 'foo.bar' is not interpreted as a path because the key exists
d['foo.bar'] = 'baz'
</code></pre>
<p>But there's a particular case, if a <em>dotted key</em> exists and match an existing <em>path</em>, then this ain't work properly, or work in a different way depending on the method of access used, to be correct</p>
<pre><code>d = MyDict({'foo': {'bar': 'baz'}, 'foo.bar': 'BAZ'})
...
d['foo.bar'] = 'BAZ' # the "dotted field" ('foo.bar') has precedence over the path
d.foo.bar = 'baz' # it's not possible to detect a "dotted key" using "dot notation"
</code></pre>
<p>Personally, I don't see this as a great issue because I generally avoid using dots in keys, like in the previous case</p>
<p>The tests passed successfully with <strong>Python 3.6</strong> and <strong>Python 2.7</strong> versions.</p>
<pre><code>$ pytest mydict -v
</code></pre>
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 Distribution
mydict-1.0.3.tar.gz
(4.2 kB
view hashes)
Built Distribution
mydict-1.0.3-py3-none-any.whl
(7.1 kB
view hashes)