Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

A dataclass as a key to a defaultdict: KeyError

Please explain and maybe help how to fix defaultdict with a frozen dataclass key.

Example:

"""Reproduce KeyError: defaultdict with dataclass keys"""

import collections
import dataclasses
import unittest


@dataclasses.dataclass(frozen=True)
class ReservationCoverageKey:
    """AWS RDS Reservation dimensions"""

    database_engine: str
    instance_family: str
    region: str


class TestCase(unittest.TestCase):
    """Main test cases"""

    def test_dict_with_dataclass_keys(self):
        """Test normal dict with dataclass key"""
        result = {}
        key = ReservationCoverageKey(
            database_engine="PostgreSQL",
            instance_family="db.t3",
            region="eu-west-1",
        )
        result[key] = 0
        result[key] += 1
        result[key] += 2
        self.assertEqual(result[key], 3)

    def test_defaultdict_with_dataclass_keys(self):
        """Test defaultdict with dataclass key"""
        result = collections.defaultdict(default_factory=int)
        key = ReservationCoverageKey(
            database_engine="PostgreSQL",
            instance_family="db.t3",
            region="eu-west-1",
        )
        result[key] += 1
        result[key] += 2
        self.assertEqual(result[key], 3)


if __name__ == "__main__":
    unittest.main()

Reproduce:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

$ python3 defaultdict_keyerror_reproduce.py 
E.
======================================================================
ERROR: test_defaultdict_with_dataclass_keys (__main__.TestCase)
Test defaultdict with dataclass key
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/var/tmp/sscce/defaultdict_keyerror_reproduce.py", line 41, in test_defaultdict_with_dataclass_keys
    result[key] += 1
KeyError: ReservationCoverageKey(database_engine='PostgreSQL', instance_family='db.t3', region='eu-west-1')

----------------------------------------------------------------------
Ran 2 tests in 0.000s

FAILED (errors=1)

The testcase with dict works, but not with the defaultdict.

>Solution :

collections.defaultdict(default_factory=int) creates a default dict with no default value type, and one value (the type int at the key "default_factory") because default_factory can only be passed as positional argument. Any keyword arguments are considered key-value pairs for the dictionary:

defaultdict(None, {'default_factory': int})

You need to do collections.defaultdict(int), which produces defaultdict(int, {})

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading