updated from Atlas
This commit is contained in:
30
03-dict-set/dialcodes.py
Normal file
30
03-dict-set/dialcodes.py
Normal file
@@ -0,0 +1,30 @@
|
||||
# BEGIN DIALCODES
|
||||
# dial codes of the top 10 most populous countries
|
||||
DIAL_CODES = [
|
||||
(86, 'China'),
|
||||
(91, 'India'),
|
||||
(1, 'United States'),
|
||||
(62, 'Indonesia'),
|
||||
(55, 'Brazil'),
|
||||
(92, 'Pakistan'),
|
||||
(880, 'Bangladesh'),
|
||||
(234, 'Nigeria'),
|
||||
(7, 'Russia'),
|
||||
(81, 'Japan'),
|
||||
]
|
||||
|
||||
d1 = dict(DIAL_CODES) # <1>
|
||||
print('d1:', d1.keys())
|
||||
d2 = dict(sorted(DIAL_CODES)) # <2>
|
||||
print('d2:', d2.keys())
|
||||
d3 = dict(sorted(DIAL_CODES, key=lambda x:x[1])) # <3>
|
||||
print('d3:', d3.keys())
|
||||
assert d1 == d2 and d2 == d3 # <4>
|
||||
# END DIALCODES
|
||||
"""
|
||||
# BEGIN DIALCODES_OUTPUT
|
||||
d1: dict_keys([880, 1, 86, 55, 7, 234, 91, 92, 62, 81])
|
||||
d2: dict_keys([880, 1, 91, 86, 81, 55, 234, 7, 92, 62])
|
||||
d3: dict_keys([880, 81, 1, 86, 55, 7, 234, 91, 92, 62])
|
||||
# END DIALCODES_OUTPUT
|
||||
"""
|
||||
25
03-dict-set/index.py
Normal file
25
03-dict-set/index.py
Normal file
@@ -0,0 +1,25 @@
|
||||
# adapted from Alex Martelli's example in "Re-learning Python"
|
||||
# http://www.aleax.it/Python/accu04_Relearn_Python_alex.pdf
|
||||
# (slide 41) Ex: lines-by-word file index
|
||||
|
||||
# BEGIN INDEX
|
||||
"""Build an index mapping word -> list of occurrences"""
|
||||
|
||||
import sys
|
||||
import re
|
||||
|
||||
WORD_RE = re.compile('\w+')
|
||||
|
||||
index = {}
|
||||
with open(sys.argv[1], encoding='utf-8') as fp:
|
||||
for line_no, line in enumerate(fp, 1):
|
||||
for match in WORD_RE.finditer(line):
|
||||
word = match.group()
|
||||
column_no = match.start()+1
|
||||
location = (line_no, column_no)
|
||||
index.setdefault(word, []).append(location) # <1>
|
||||
|
||||
# print in alphabetical order
|
||||
for word in sorted(index, key=str.upper):
|
||||
print(word, index[word])
|
||||
# END INDEX
|
||||
28
03-dict-set/index0.py
Normal file
28
03-dict-set/index0.py
Normal file
@@ -0,0 +1,28 @@
|
||||
# adapted from Alex Martelli's example in "Re-learning Python"
|
||||
# http://www.aleax.it/Python/accu04_Relearn_Python_alex.pdf
|
||||
# (slide 41) Ex: lines-by-word file index
|
||||
|
||||
# BEGIN INDEX0
|
||||
"""Build an index mapping word -> list of occurrences"""
|
||||
|
||||
import sys
|
||||
import re
|
||||
|
||||
WORD_RE = re.compile('\w+')
|
||||
|
||||
index = {}
|
||||
with open(sys.argv[1], encoding='utf-8') as fp:
|
||||
for line_no, line in enumerate(fp, 1):
|
||||
for match in WORD_RE.finditer(line):
|
||||
word = match.group()
|
||||
column_no = match.start()+1
|
||||
location = (line_no, column_no)
|
||||
# this is ugly; coded like this to make a point
|
||||
occurrences = index.get(word, []) # <1>
|
||||
occurrences.append(location) # <2>
|
||||
index[word] = occurrences # <3>
|
||||
|
||||
# print in alphabetical order
|
||||
for word in sorted(index, key=str.upper): # <4>
|
||||
print(word, index[word])
|
||||
# END INDEX0
|
||||
26
03-dict-set/index_default.py
Normal file
26
03-dict-set/index_default.py
Normal file
@@ -0,0 +1,26 @@
|
||||
# adapted from Alex Martelli's example in "Re-learning Python"
|
||||
# http://www.aleax.it/Python/accu04_Relearn_Python_alex.pdf
|
||||
# (slide 41) Ex: lines-by-word file index
|
||||
|
||||
# BEGIN INDEX_DEFAULT
|
||||
"""Build an index mapping word -> list of occurrences"""
|
||||
|
||||
import sys
|
||||
import re
|
||||
import collections
|
||||
|
||||
WORD_RE = re.compile('\w+')
|
||||
|
||||
index = collections.defaultdict(list) # <1>
|
||||
with open(sys.argv[1], encoding='utf-8') as fp:
|
||||
for line_no, line in enumerate(fp, 1):
|
||||
for match in WORD_RE.finditer(line):
|
||||
word = match.group()
|
||||
column_no = match.start()+1
|
||||
location = (line_no, column_no)
|
||||
index[word].append(location) # <2>
|
||||
|
||||
# print in alphabetical order
|
||||
for word in sorted(index, key=str.upper):
|
||||
print(word, index[word])
|
||||
# END INDEX_DEFAULT
|
||||
74
03-dict-set/strkeydict.py
Normal file
74
03-dict-set/strkeydict.py
Normal file
@@ -0,0 +1,74 @@
|
||||
"""StrKeyDict always converts non-string keys to `str`
|
||||
|
||||
Test for initializer: keys are converted to `str`.
|
||||
|
||||
>>> d = StrKeyDict([(2, 'two'), ('4', 'four')])
|
||||
>>> sorted(d.keys())
|
||||
['2', '4']
|
||||
|
||||
Tests for item retrieval using `d[key]` notation::
|
||||
|
||||
>>> d['2']
|
||||
'two'
|
||||
>>> d[4]
|
||||
'four'
|
||||
>>> d[1]
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
KeyError: '1'
|
||||
|
||||
Tests for item retrieval using `d.get(key)` notation::
|
||||
|
||||
>>> d.get('2')
|
||||
'two'
|
||||
>>> d.get(4)
|
||||
'four'
|
||||
>>> d.get(1, 'N/A')
|
||||
'N/A'
|
||||
|
||||
Tests for the `in` operator::
|
||||
|
||||
>>> 2 in d
|
||||
True
|
||||
>>> 1 in d
|
||||
False
|
||||
|
||||
Test for item assignment using non-string key::
|
||||
|
||||
>>> d[0] = 'zero'
|
||||
>>> d['0']
|
||||
'zero'
|
||||
|
||||
Tests for update using a `dict` or a sequence of pairs::
|
||||
|
||||
>>> d.update({6:'six', '8':'eight'})
|
||||
>>> sorted(d.keys())
|
||||
['0', '2', '4', '6', '8']
|
||||
>>> d.update([(10, 'ten'), ('12', 'twelve')])
|
||||
>>> sorted(d.keys())
|
||||
['0', '10', '12', '2', '4', '6', '8']
|
||||
>>> d.update([1, 3, 5])
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
TypeError: 'int' object is not iterable
|
||||
|
||||
"""
|
||||
# BEGIN STRKEYDICT
|
||||
|
||||
import collections
|
||||
|
||||
|
||||
class StrKeyDict(collections.UserDict): # <1>
|
||||
|
||||
def __missing__(self, key): # <2>
|
||||
if isinstance(key, str):
|
||||
raise KeyError(key)
|
||||
return self[str(key)]
|
||||
|
||||
def __contains__(self, key):
|
||||
return str(key) in self.data # <3>
|
||||
|
||||
def __setitem__(self, key, item):
|
||||
self.data[str(key)] = item # <4>
|
||||
|
||||
# END STRKEYDICT
|
||||
55
03-dict-set/strkeydict0.py
Normal file
55
03-dict-set/strkeydict0.py
Normal file
@@ -0,0 +1,55 @@
|
||||
"""StrKeyDict0 converts non-string keys to `str` on lookup
|
||||
|
||||
# BEGIN STRKEYDICT0_TESTS
|
||||
|
||||
Tests for item retrieval using `d[key]` notation::
|
||||
|
||||
>>> d = StrKeyDict0([('2', 'two'), ('4', 'four')])
|
||||
>>> d['2']
|
||||
'two'
|
||||
>>> d[4]
|
||||
'four'
|
||||
>>> d[1]
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
KeyError: '1'
|
||||
|
||||
Tests for item retrieval using `d.get(key)` notation::
|
||||
|
||||
>>> d.get('2')
|
||||
'two'
|
||||
>>> d.get(4)
|
||||
'four'
|
||||
>>> d.get(1, 'N/A')
|
||||
'N/A'
|
||||
|
||||
|
||||
Tests for the `in` operator::
|
||||
|
||||
>>> 2 in d
|
||||
True
|
||||
>>> 1 in d
|
||||
False
|
||||
|
||||
# END STRKEYDICT0_TESTS
|
||||
"""
|
||||
|
||||
|
||||
# BEGIN STRKEYDICT0
|
||||
class StrKeyDict0(dict): # <1>
|
||||
|
||||
def __missing__(self, key):
|
||||
if isinstance(key, str): # <2>
|
||||
raise KeyError(key)
|
||||
return self[str(key)] # <3>
|
||||
|
||||
def get(self, key, default=None):
|
||||
try:
|
||||
return self[key] # <4>
|
||||
except KeyError:
|
||||
return default # <5>
|
||||
|
||||
def __contains__(self, key):
|
||||
return key in self.keys() or str(key) in self.keys() # <6>
|
||||
|
||||
# END STRKEYDICT0
|
||||
142
03-dict-set/transformdict.py
Normal file
142
03-dict-set/transformdict.py
Normal file
@@ -0,0 +1,142 @@
|
||||
"""Transformdict: a mapping that transforms keys on lookup
|
||||
|
||||
This module and ``test_transformdict.py`` were extracted from a
|
||||
patch contributed to Python by Antoine Pitrou implementing his
|
||||
PEP 455 -- Adding a key-transforming dictionary to collections.
|
||||
|
||||
As of Nov. 14, 2014, the patch was not yet merged to Python 3.5
|
||||
(which is in pre-alpha). The patch is ``transformdict3.patch``,
|
||||
part of issue #18986: Add a case-insensitive case-preserving dict.
|
||||
|
||||
http://bugs.python.org/issue18986
|
||||
"""
|
||||
|
||||
from collections.abc import MutableMapping
|
||||
|
||||
|
||||
_sentinel = object()
|
||||
|
||||
|
||||
class TransformDict(MutableMapping):
|
||||
'''Dictionary that calls a transformation function when looking
|
||||
up keys, but preserves the original keys.
|
||||
|
||||
>>> d = TransformDict(str.lower)
|
||||
>>> d['Foo'] = 5
|
||||
>>> d['foo'] == d['FOO'] == d['Foo'] == 5
|
||||
True
|
||||
>>> set(d.keys())
|
||||
{'Foo'}
|
||||
'''
|
||||
|
||||
__slots__ = ('_transform', '_original', '_data')
|
||||
|
||||
def __init__(self, transform, init_dict=None, **kwargs):
|
||||
'''Create a new TransformDict with the given *transform* function.
|
||||
*init_dict* and *kwargs* are optional initializers, as in the
|
||||
dict constructor.
|
||||
'''
|
||||
if not callable(transform):
|
||||
msg = 'expected a callable, got %r'
|
||||
raise TypeError(msg % transform.__class__)
|
||||
self._transform = transform
|
||||
# transformed => original
|
||||
self._original = {}
|
||||
self._data = {}
|
||||
if init_dict:
|
||||
self.update(init_dict)
|
||||
if kwargs:
|
||||
self.update(kwargs)
|
||||
|
||||
def getitem(self, key):
|
||||
'D.getitem(key) -> (stored key, value)'
|
||||
transformed = self._transform(key)
|
||||
original = self._original[transformed]
|
||||
value = self._data[transformed]
|
||||
return original, value
|
||||
|
||||
@property
|
||||
def transform_func(self):
|
||||
"This TransformDict's transformation function"
|
||||
return self._transform
|
||||
|
||||
# Minimum set of methods required for MutableMapping
|
||||
|
||||
def __len__(self):
|
||||
return len(self._data)
|
||||
|
||||
def __iter__(self):
|
||||
return iter(self._original.values())
|
||||
|
||||
def __getitem__(self, key):
|
||||
return self._data[self._transform(key)]
|
||||
|
||||
def __setitem__(self, key, value):
|
||||
transformed = self._transform(key)
|
||||
self._data[transformed] = value
|
||||
self._original.setdefault(transformed, key)
|
||||
|
||||
def __delitem__(self, key):
|
||||
transformed = self._transform(key)
|
||||
del self._data[transformed]
|
||||
del self._original[transformed]
|
||||
|
||||
# Methods overridden to mitigate the performance overhead.
|
||||
|
||||
def clear(self):
|
||||
'D.clear() -> None. Remove all items from D.'
|
||||
self._data.clear()
|
||||
self._original.clear()
|
||||
|
||||
def __contains__(self, key):
|
||||
return self._transform(key) in self._data
|
||||
|
||||
def get(self, key, default=None):
|
||||
'D.get(k[,d]) -> D[k] if k in D, else d. d defaults to None.'
|
||||
return self._data.get(self._transform(key), default)
|
||||
|
||||
def pop(self, key, default=_sentinel):
|
||||
'''D.pop(k[,d]) -> v, remove key and return corresponding value.
|
||||
If key is not found, d is returned if given, otherwise
|
||||
KeyError is raised.
|
||||
'''
|
||||
transformed = self._transform(key)
|
||||
if default is _sentinel:
|
||||
del self._original[transformed]
|
||||
return self._data.pop(transformed)
|
||||
else:
|
||||
self._original.pop(transformed, None)
|
||||
return self._data.pop(transformed, default)
|
||||
|
||||
def popitem(self):
|
||||
'''D.popitem() -> (k, v), remove and return some (key, value) pair
|
||||
as a 2-tuple; but raise KeyError if D is empty.
|
||||
'''
|
||||
transformed, value = self._data.popitem()
|
||||
return self._original.pop(transformed), value
|
||||
|
||||
# Other methods
|
||||
|
||||
def copy(self):
|
||||
'D.copy() -> a shallow copy of D'
|
||||
other = self.__class__(self._transform)
|
||||
other._original = self._original.copy()
|
||||
other._data = self._data.copy()
|
||||
return other
|
||||
|
||||
__copy__ = copy
|
||||
|
||||
def __getstate__(self):
|
||||
return (self._transform, self._data, self._original)
|
||||
|
||||
def __setstate__(self, state):
|
||||
self._transform, self._data, self._original = state
|
||||
|
||||
def __repr__(self):
|
||||
try:
|
||||
equiv = dict(self)
|
||||
except TypeError:
|
||||
# Some keys are unhashable, fall back on .items()
|
||||
equiv = list(self.items())
|
||||
return '%s(%r, %s)' % (self.__class__.__name__,
|
||||
self._transform, repr(equiv))
|
||||
Reference in New Issue
Block a user