具有非平凡默认值的默认字典
Default dict with a non-trivial default
我想创建一个“默认字典”,它对丢失的键执行重要的操作(例如,数据库查找)。我在这里看到了一些旧的答案,比如 Using the key in collections.defaultdict,建议子类化 collections.defaultdict
。
虽然这是有道理的,但此时是否有理由使用 defaultdict
。为什么不简单地继承 dict
并覆盖它的 __missing__
方法呢? defaultdict
是否提供了我可以通过子类化获得的其他东西?
defaultdict
加什么?
根据 the documentation,defaultdict
和内置 dict
之间的唯一区别是:
It overrides one method and adds one writable instance variable.
一个方法是__missing__
方法,当访问不存在的键时调用。
而一个可写实例变量是default_factory
——一个没有参数的可调用对象,__missing__
使用它来确定要使用的默认值缺少钥匙。
大致相当于:
def __missing__(self, key):
if self.default_factory is None:
raise KeyError(key)
self[key] = self.default_factory()
return self[key]
什么时候继承?
重要的是要明确指出,您甚至需要创建子类的唯一原因是缺少键的默认值 取决于实际键。如果您的默认工厂不需要密钥 - 无论逻辑多么复杂,您都可以 使用 defaultdict
而不是继承。如果 lambda
的逻辑太多了,你当然仍然可以创建一个函数并使用它:
def calc():
# very long code
# calculating a static new key
# (maybe a DB request to fetch the latest record...)
return new_value
d = defaultdict(calc)
如果你确实需要key本身来计算默认值,那么你需要继承:
何时从 defaultdict
继承?
主要优点是,如果您希望能够拥有一个动态工厂(即在运行时更改 default_factory
),这可以让您省去自己实现它的麻烦(无需覆盖 __init__
...).
但是,请注意,这意味着您在覆盖 __missing__
时必须考虑此 default_factory
的存在,如 this answer.[=32 中所示=]
何时从 dict
继承
当您不关心动态更改工厂并且可以满足于整个 dict 存在期间的静态工厂时。
在这种情况下,您只需覆盖 __missing__
方法并使用依赖于密钥的任何复杂逻辑来实现工厂。
我想创建一个“默认字典”,它对丢失的键执行重要的操作(例如,数据库查找)。我在这里看到了一些旧的答案,比如 Using the key in collections.defaultdict,建议子类化 collections.defaultdict
。
虽然这是有道理的,但此时是否有理由使用 defaultdict
。为什么不简单地继承 dict
并覆盖它的 __missing__
方法呢? defaultdict
是否提供了我可以通过子类化获得的其他东西?
defaultdict
加什么?
根据 the documentation,defaultdict
和内置 dict
之间的唯一区别是:
It overrides one method and adds one writable instance variable.
一个方法是__missing__
方法,当访问不存在的键时调用。
而一个可写实例变量是default_factory
——一个没有参数的可调用对象,__missing__
使用它来确定要使用的默认值缺少钥匙。
大致相当于:
def __missing__(self, key):
if self.default_factory is None:
raise KeyError(key)
self[key] = self.default_factory()
return self[key]
什么时候继承?
重要的是要明确指出,您甚至需要创建子类的唯一原因是缺少键的默认值 取决于实际键。如果您的默认工厂不需要密钥 - 无论逻辑多么复杂,您都可以 使用 defaultdict
而不是继承。如果 lambda
的逻辑太多了,你当然仍然可以创建一个函数并使用它:
def calc():
# very long code
# calculating a static new key
# (maybe a DB request to fetch the latest record...)
return new_value
d = defaultdict(calc)
如果你确实需要key本身来计算默认值,那么你需要继承:
何时从 defaultdict
继承?
主要优点是,如果您希望能够拥有一个动态工厂(即在运行时更改 default_factory
),这可以让您省去自己实现它的麻烦(无需覆盖 __init__
...).
但是,请注意,这意味着您在覆盖 __missing__
时必须考虑此 default_factory
的存在,如 this answer.[=32 中所示=]
何时从 dict
继承
当您不关心动态更改工厂并且可以满足于整个 dict 存在期间的静态工厂时。
在这种情况下,您只需覆盖 __missing__
方法并使用依赖于密钥的任何复杂逻辑来实现工厂。