example-code-2e/14-inheritance/uppermixin.py

141 lines
3.0 KiB
Python
Raw Normal View History

2021-08-07 05:44:01 +02:00
"""
Short demos
===========
2021-08-07 00:51:22 +02:00
2021-08-07 05:44:01 +02:00
``UpperDict`` behaves like a case-insensitive mapping`::
2021-08-07 00:51:22 +02:00
2021-08-07 05:44:01 +02:00
# tag::UPPERDICT_DEMO[]
>>> d = UpperDict([('a', 'letter A'), (2, 'digit two')])
2021-08-07 00:51:22 +02:00
>>> list(d.keys())
2021-08-07 05:44:01 +02:00
['A', 2]
>>> d['b'] = 'letter B'
>>> 'b' in d
True
>>> d['a'], d.get('B')
('letter A', 'letter B')
>>> list(d.keys())
['A', 2, 'B']
# end::UPPERDICT_DEMO[]
And ``UpperCounter`` is also case-insensitive::
# tag::UPPERCOUNTER_DEMO[]
>>> c = UpperCounter('BaNanA')
>>> c.most_common()
[('A', 3), ('N', 2), ('B', 1)]
# end::UPPERCOUNTER_DEMO[]
Detailed tests
==============
UpperDict uppercases all string keys.
>>> d = UpperDict([('a', 'letter A'), ('B', 'letter B'), (2, 'digit two')])
2021-08-07 00:51:22 +02:00
Tests for item retrieval using `d[key]` notation::
>>> d['A']
'letter A'
>>> d['b']
'letter B'
>>> d[2]
'digit two'
Tests for missing key::
>>> d['z']
Traceback (most recent call last):
...
KeyError: 'Z'
>>> d[99]
Traceback (most recent call last):
...
KeyError: 99
Tests for item retrieval using `d.get(key)` notation::
>>> d.get('a')
'letter A'
>>> d.get('B')
'letter B'
>>> d.get(2)
'digit two'
>>> d.get('z', '(not found)')
'(not found)'
Tests for the `in` operator::
>>> ('a' in d, 'B' in d, 'z' in d)
(True, True, False)
Test for item assignment using lowercase key::
>>> d['c'] = 'letter C'
>>> d['C']
'letter C'
Tests for update using a `dict` or a sequence of pairs::
>>> d.update({'D': 'letter D', 'e': 'letter E'})
>>> list(d.keys())
['A', 'B', 2, 'C', 'D', 'E']
>>> d.update([('f', 'letter F'), ('G', 'letter G')])
>>> list(d.keys())
['A', 'B', 2, 'C', 'D', 'E', 'F', 'G']
>>> d # doctest:+NORMALIZE_WHITESPACE
{'A': 'letter A', 'B': 'letter B', 2: 'digit two',
'C': 'letter C', 'D': 'letter D', 'E': 'letter E',
'F': 'letter F', 'G': 'letter G'}
UpperCounter uppercases all `str` keys.
Test for initializer: keys are uppercased.
>>> d = UpperCounter('AbracAdaBrA')
>>> sorted(d.keys())
['A', 'B', 'C', 'D', 'R']
Tests for count retrieval using `d[key]` notation::
>>> d['a']
5
>>> d['z']
0
"""
# tag::UPPERCASE_MIXIN[]
import collections
def _upper(key): # <1>
try:
return key.upper()
except AttributeError:
return key
class UpperCaseMixin: # <2>
def __setitem__(self, key, item):
super().__setitem__(_upper(key), item)
def __getitem__(self, key):
return super().__getitem__(_upper(key))
def get(self, key, default=None):
return super().get(_upper(key), default)
def __contains__(self, key):
return super().__contains__(_upper(key))
# end::UPPERCASE_MIXIN[]
# tag::UPPERDICT[]
class UpperDict(UpperCaseMixin, collections.UserDict): # <1>
pass
class UpperCounter(UpperCaseMixin, collections.Counter): # <2>
"""Specialized 'Counter' that uppercases string keys""" # <3>
# end::UPPERDICT[]