Two dial keys
I would suggest abandoning the idea of embedding dictionaries and just use the two tuples as keys directly. For instance:
d = { (user_id, analysis_type_id): count for count, analysis_type_id, user_id in counts}
- -. python ( ), () . ( 2 , ), ( user_id
, analysis_type_id
).
. , dict
. , , .. , , , .
namedtuple
. :
from collections import namedtuple
IdPair = namedtuple("IdPair", "user_id, analysis_type_id")
:
d = { IdPair(user_id, analysis_type_id): count for count, analysis_type_id, user_id in counts}
:
somepair = IdPair(user_id = 4, analysis_type_id = 1)
d[somepair]
, , - :
user_id = somepair.user_id
- , . :
>>> d[IdPair(0,0)]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: IdPair(user_id=0, analysis_type_id=0)
; user_id
, analysis_type_id
, ?
, dict
, . :
class CountsDict(dict):
"""A dict for storing IdPair keys and count values as integers.
Provides more detailed traceback information than a regular dict.
"""
def __getitem__(self, k):
try:
return super().__getitem__(k)
except KeyError as exc:
raise self._handle_bad_key(k, exc) from exc
def _handle_bad_key(self, k, exc):
"""Provides a custom exception when a bad key is given."""
try:
user_id, analysis_type_id = k
except:
return exc
has_u_id = next((True for u_id, _ in self if u_id==user_id), False)
has_at_id = next((True for _, at_id in self if at_id==analysis_type_id), False)
exc_lookup = {(False, False):KeyError(f"CountsDict missing pair: {k}"),
(True, False):KeyError(f"CountsDict missing analysis_type_id: "
f"{analysis_type_id}"),
(False, True):KeyError(f"CountsDict missing user_id: {user_id}")}
return exc_lookup[(user_id, analysis_type_id)]
, dict
.
, dict
( ). , defaultdict
( int
factory) . :
from collections import defaultdict
my_dict = defaultdict(default_factory=int,
((user_id, analysis_type_id), count) for count, analysis_type_id, user_id in counts))
, , . , :
value = my_dict['I'm not a two tuple, sucka!!!!']
, CountsDict
, , dict
defaultdict
. , defaultdict
, , . , , , IdPair
.
from collections import defaultdict
class CountsDict(defaultdict):
"""A dict for storing IdPair keys and count values as integers.
Missing two-tuple keys are converted to an IdPair. Invalid keys raise a KeyError.
"""
def __getitem__(self, k):
try:
user_id, analysis_type_id = k
except:
raise KeyError(f"The provided key {k!r} is not a valid key.")
else:
k = IdPair(user_id, analysis_type_id)
return super().__getitem__(k)
, defaultdict
:
my_dict = CountsDict(default_factory=int,
((user_id, analysis_type_id), count) for count, analysis_type_id, user_id in counts))
. , IdPair
( __setitem__
). , __init__
.
.