作为 defaultdict 键的数据类:KeyError
A dataclass as a key to a defaultdict: KeyError
请解释并可能帮助如何使用冻结的 dataclass
密钥修复 defaultdict
。
示例:
"""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()
复制:
$ 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)
带有 dict
的测试用例有效,但不适用于 defaultdict
。
是否有任何理由使用 result = collections.defaultdict(default_factory=int)
而不是 result = collections.defaultdict(int)
?
如果你这样改,它就会通过测试。我不知道为什么它不接受你声明的。
我认为它不接受默认键作为关键字参数。
示例:
import collections
result = collections.defaultdict(default_factory=int)
result2 = collections.defaultdict(int)
result3 = collections.defaultdict()
print(result)
print(result2)
print(result3)
#output:
> defaultdict(None, {'default_factory': <class 'int'>})
> defaultdict(<class 'int'>, {})
> defaultdict(None, {})
当您传递 default_factory
属性 时,它不会将其指定为默认键,因为它是位置参数。所以,您遇到了 KeyError。
collections.defaultdict(default_factory=int)
创建一个没有默认值类型的默认dict,只有一个值(键"default_factory"
处的类型int
)因为default_factory
只能传递作为位置参数。任何关键字参数都被视为字典的键值对:
defaultdict(None, {'default_factory': int})
您需要执行 collections.defaultdict(int)
,这会产生 defaultdict(int, {})
请解释并可能帮助如何使用冻结的 dataclass
密钥修复 defaultdict
。
示例:
"""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()
复制:
$ 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)
带有 dict
的测试用例有效,但不适用于 defaultdict
。
是否有任何理由使用 result = collections.defaultdict(default_factory=int)
而不是 result = collections.defaultdict(int)
?
如果你这样改,它就会通过测试。我不知道为什么它不接受你声明的。
我认为它不接受默认键作为关键字参数。
示例:
import collections
result = collections.defaultdict(default_factory=int)
result2 = collections.defaultdict(int)
result3 = collections.defaultdict()
print(result)
print(result2)
print(result3)
#output:
> defaultdict(None, {'default_factory': <class 'int'>})
> defaultdict(<class 'int'>, {})
> defaultdict(None, {})
当您传递 default_factory
属性 时,它不会将其指定为默认键,因为它是位置参数。所以,您遇到了 KeyError。
collections.defaultdict(default_factory=int)
创建一个没有默认值类型的默认dict,只有一个值(键"default_factory"
处的类型int
)因为default_factory
只能传递作为位置参数。任何关键字参数都被视为字典的键值对:
defaultdict(None, {'default_factory': int})
您需要执行 collections.defaultdict(int)
,这会产生 defaultdict(int, {})