如何制作一个python字典,为字典中缺少的键返回键,而不是引发keyrerror?

如何制作一个python字典,为字典中缺少的键返回键,而不是引发keyrerror?,python,dictionary,data-structures,dictionary-missing,Python,Dictionary,Data Structures,Dictionary Missing,我想创建一个python字典,它返回字典中缺少的键的键值 用法示例: dic = smart_dict() dic['a'] = 'one a' print(dic['a']) # >>> one a print(dic['b']) # >>> b 子类dict的\uu getitem\uuu方法。例如,为什么不直接使用 dic.get('b', 'b') 当然,您可以像其他人指出的那样将dict子类化,但我发现偶尔提醒自己get可以有一个默认值非常方便

我想创建一个python字典,它返回字典中缺少的键的键值

用法示例:

dic = smart_dict()
dic['a'] = 'one a'
print(dic['a'])
# >>> one a
print(dic['b'])
# >>> b

子类
dict
\uu getitem\uuu
方法。例如,

为什么不直接使用

dic.get('b', 'b')
当然,您可以像其他人指出的那样将
dict
子类化,但我发现偶尔提醒自己
get
可以有一个默认值非常方便

如果要尝试使用
defaultdict
,请尝试以下操作:

dic = defaultdict()
dic.__missing__ = lambda key: key
dic['b'] # should set dic['b'] to 'b' and return 'b'
除了。。。好:
AttributeError:^collections.defaultdict^对象属性“\uuu missing\uuuuu”是只读的
,因此您必须子类化:

from collections import defaultdict
class KeyDict(defaultdict):
    def __missing__(self, key):
        return key

d = KeyDict()
print d['b'] #prints 'b'
print d.keys() #prints []
dict
s对此有一个钩子:

class smart_dict(dict):
    def __missing__(self, key):
        return key

第一位受访者提到了defaultdict, 但是您可以为dict的任何子类定义
\uuuu missing\uuuu

>>> class Dict(dict):
        def __missing__(self, key):
            return key


>>> d = Dict(a=1, b=2)
>>> d['a']
1
>>> d['z']
'z'
此外,我喜欢第二位受访者的方法:

>>> d = dict(a=1, b=2)
>>> d.get('z', 'z')
'z'

祝贺您。您也发现了 标准
集合。默认dict
类型。如果那可恶的中间一堆 和我一样冒犯了你脆弱的感情,这是你的幸运 这是一天

多亏了
type()
内置,制作一个非无用的默认字典类型既有趣又有利可图

迪克特怎么了?____;失踪了?__;()? 绝对没什么,假设你喜欢过多的样板文件和
collections.defaultdict
令人震惊的愚蠢——它的行为应该和预期的一样,但实际上并没有。公平地说,子类化
dict
和 实现的是一个奇妙的过程 针对只需要一个默认字典的小规模用例的变通方法

但这类样板文件的伸缩性很差。如果您发现自己正在实例化 多个默认字典,每个字典的逻辑略有不同 生成缺失的键值对,一种工业实力替代方案 自动化样板是有保证的

或者至少很好。因为为什么不修理坏了的东西

介绍DefaultDict 在不到十行的纯Python中(不包括docstring、注释和 空白),我们现在定义一个
DefaultDict
类型,该类型使用用户定义的 可调用为缺少的键生成默认值。而可调用函数通过了 到标准的
集合。defaultdict
类型无效地接受no 参数,传递给我们的
DefaultDict
类型的可调用函数有效地接受 以下两个参数:

  • 此词典的当前实例
  • 要为其生成默认值的当前缺少的键
  • 考虑到这种类型,解决 问题归结为一行Python:

    >>> dic = DefaultDict(lambda self, missing_key: missing_key)
    >>> dic['a'] = 'one a'
    >>> print(dic['a'])
    one a
    >>> print(dic['b'])
    b
    
    理智。终于

    密码,否则就不会发生 钥匙…拿到了,钥匙?对这种神秘的巫术的召唤是 这个 内置的
    type()

    type(default_dict_class_name, (dict,), {'__missing__': keygen,})
    
    这一行动态地生成一个新的
    dict
    子类,为 调用方定义的可调用的可选
    \uuu缺少\uuu
    方法。注意不同的 缺少样板文件,将
    DefaultDict
    的使用减少到一行Python


    自动实现惊人的胜利。

    我同意这应该很容易做到,也很容易设置不同的默认值或函数,以某种方式转换丢失的值

    受的启发,我问自己:为什么不让默认生成器(常量或可调用生成器)作为类的成员,而不是一直生成不同的类?让我示范一下:

    # default behaviour: return missing keys unchanged
    dic = FlexDict()
    dic['a'] = 'one a'
    print(dic['a'])
    # 'one a'
    print(dic['b'])
    # 'b'
    
    # regardless of default: easy initialisation with existing dictionary
    existing_dic = {'a' : 'one a'}
    dic = FlexDict(existing_dic)
    print(dic['a'])
    # 'one a'
    print(dic['b'])
    # 'b'
    
    # using constant as default for missing values
    dic = FlexDict(existing_dic, default = 10)
    print(dic['a'])
    # 'one a'
    print(dic['b'])
    # 10
    
    # use callable as default for missing values
    dic = FlexDict(existing_dic, default = lambda missing_key: missing_key * 2)
    print(dic['a'])
    # 'one a'
    print(dic['b'])
    # 'bb'
    print(dic[2])
    # 4
    
    它是如何工作的?没那么难:

    class FlexDict(dict):
        '''Subclass of dictionary which returns a default for missing keys.
        This default can either be a constant, or a callable accepting the missing key.
        If "default" is not given (or None), each missing key will be returned unchanged.'''
        def __init__(self, content = None, default = None):
            if content is None:
                super().__init__()
            else:
                super().__init__(content)
            if default is None:
                default = lambda missing_key: missing_key
            self.default = default # sets self._default
    
        @property
        def default(self):
            return self._default
    
        @default.setter
        def default(self, val):
            if callable(val):
                self._default = val
            else: # constant value
                self._default = lambda missing_key: val
    
        def __missing__(self, x):
            return self.default(x)
    
    当然,人们可以争论是否允许在初始化后更改默认函数,但这只意味着删除
    @default.setter
    ,并将其逻辑吸收到
    \uuuu init\uu


    在当前(常量)默认值中启用内省功能可以添加两行额外的代码。

    我本来希望通过
    collections.defautldict()
    可以获得这种行为,但由于某些原因,我缺少一些关于它如何工作的信息。有很多方法可以做到这一点。一个可能重要的区别/考虑因素是,他们是否也将缺少的键添加到基础字典中。此外,文档说“除了标准dict操作之外,defaultdict对象还支持[
    \uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu?我猜missing是defaultdict工作的主要方法,请记住,
    smart_dict()['a']
    返回
    'a'
    smart_dict().get('a')
    返回
    None
    (或作为默认值传递的任何值),这可能不是期望的行为。为什么子类
    defaultdict
    与子类
    dict
    相比?酷,不知道三参数变量!我同意你的观点(因此
    defaultdict
    需要一个政治公众人物?),但是我想大多数人只需要一个“理智的”
    defaultdict
    ,而不需要工业实力阶层。实际上,为什么要创建许多类呢?为什么不将默认值(可调用)作为类的成员?这激发了我写作。这正是我最初的想法,但后来我意识到了可能的理由。似乎作者最初的想法是这样使用构造函数:
    default\u str\u dict=defaultdict(str)
    而不是
    default\u str\u dict=defaultdict(“”)
    。无论如何,这绝对是一个糟糕的决定,导致了意想不到的行为和不便。
    class FlexDict(dict):
        '''Subclass of dictionary which returns a default for missing keys.
        This default can either be a constant, or a callable accepting the missing key.
        If "default" is not given (or None), each missing key will be returned unchanged.'''
        def __init__(self, content = None, default = None):
            if content is None:
                super().__init__()
            else:
                super().__init__(content)
            if default is None:
                default = lambda missing_key: missing_key
            self.default = default # sets self._default
    
        @property
        def default(self):
            return self._default
    
        @default.setter
        def default(self, val):
            if callable(val):
                self._default = val
            else: # constant value
                self._default = lambda missing_key: val
    
        def __missing__(self, x):
            return self.default(x)