具有默认键的Python字典

具有默认键的Python字典,python,python-2.7,dictionary,default,default-value,Python,Python 2.7,Dictionary,Default,Default Value,我正在运行Python 2.7.10 我想让字典返回存储在特定键上的值,以防丢失项。例如,类似这样的情况: myD = dict(...) return myD[key] if key in myD else myD[defaultKey] 为了确保清楚,我想调用myD[key]并返回正确的值,而不需要在我的代码中添加额外的if…else 这与defaultdict的功能不同(因为它需要一个函数作为默认值调用),也与dict.setdefault()的功能不同,myD.get(key,?)似乎

我正在运行Python 2.7.10

我想让字典返回存储在特定键上的值,以防丢失项。例如,类似这样的情况:

myD = dict(...)
return myD[key] if key in myD else myD[defaultKey]
为了确保清楚,我想调用
myD[key]
并返回正确的值,而不需要在我的代码中添加额外的
if…else


这与
defaultdict
的功能不同(因为它需要一个函数作为默认值调用),也与
dict.setdefault()
的功能不同,
myD.get(key,?)似乎也没有帮助。我可能应该从
dict
defaultdict
继承,重载
\uu init\uuu()
missing()
方法,但我想不出一个好方法来做这件事。

在你的情况下,
dict.get
应该可以工作(我知道你已经提到过它不起作用)。您是否尝试过:

myD.get(key,myD[defaultKey])

在您的情况下,
dict.get
应该会起作用(我知道您已经提到它不起作用)。您是否尝试过:

myD.get(key,myD[defaultKey])

我不完全确定你想要什么(没有阅读你问题下的所有评论),但我认为这可能至少接近你想要的

class DefaultKeyDict(dict):
    def __init__(self, default_key, *args, **kwargs):
        self.default_key = default_key
        super(DefaultKeyDict, self).__init__(*args, **kwargs)

    def __missing__ (self, key):
        if self.default_key not in self:  # default key not defined
            raise KeyError(key)
        return self[self.default_key]

    def __repr__(self):
        return ('{}({!r}, {})'.format(self.__class__.__name__,
                                      self.default_key,
                                      super(DefaultKeyDict, self).__repr__()))

    def __reduce__(self):  # optional, for pickle support
        args = (self.default_key if self.default_key in self else None,)
        return self.__class__, args, None, None, self.iteritems()

dkdict = DefaultKeyDict('b', {'a': 1, 'b': 2, 'c': 3})

print dkdict['a']  # -> 1
print dkdict['b']  # -> 2
print dkdict['c']  # -> 3
print dkdict['d']  # -> 2 (value of the default key)

del dkdict['b']  # delete the default key
try:
    print dkdict['d']  # should now raise exception like normal
except KeyError:
    print("dkdict['d'] raised a KeyError")

您可能需要修改类
\uuu init\uuu()
方法,以接受默认键及其值作为参数(而不仅仅是键)。

我不完全确定您想要什么(没有阅读您问题下的所有注释),但我认为这可能至少接近您想要的

class DefaultKeyDict(dict):
    def __init__(self, default_key, *args, **kwargs):
        self.default_key = default_key
        super(DefaultKeyDict, self).__init__(*args, **kwargs)

    def __missing__ (self, key):
        if self.default_key not in self:  # default key not defined
            raise KeyError(key)
        return self[self.default_key]

    def __repr__(self):
        return ('{}({!r}, {})'.format(self.__class__.__name__,
                                      self.default_key,
                                      super(DefaultKeyDict, self).__repr__()))

    def __reduce__(self):  # optional, for pickle support
        args = (self.default_key if self.default_key in self else None,)
        return self.__class__, args, None, None, self.iteritems()

dkdict = DefaultKeyDict('b', {'a': 1, 'b': 2, 'c': 3})

print dkdict['a']  # -> 1
print dkdict['b']  # -> 2
print dkdict['c']  # -> 3
print dkdict['d']  # -> 2 (value of the default key)

del dkdict['b']  # delete the default key
try:
    print dkdict['d']  # should now raise exception like normal
except KeyError:
    print("dkdict['d'] raised a KeyError")


您可能需要修改类
\uuu init\uuu()
方法,以接受默认键及其值作为参数(而不仅仅是键)。

您的问题是什么?你说得对,
dict.get
不会那么做;如果您想知道如何编写自己的,请查看并相应地实现
\uuu getitem\uuuu
。但是
defaultKey
应该从哪里来(它是参数?类的属性还是实例的属性?@jornsharpe是的,这是我的问题,如何实现它。我不知道如何在这种情况下使用ABCscontext@jonrsharpe是的,
defaultKey
是初始化时的参数,实例应将其存储为属性您继承它们,然后实现它们指定的方法(在本例中为
\u[get/set/del]item.\uuuu
\uuu iter.\uuuu
\uu len.\uuuu
,加上默认键值对的自定义
\uuu init.\uuuuu
。@jornsharpe我希望通过继承一个现成的对象(如
defaultdict
)并重写
\uu getitem.\uu>,可以让事情变得更简单,在其他地方留下相同的功能…你的问题是什么?你说得对,
dict.get
不会那么做;如果您想知道如何编写自己的,请查看并相应地实现
\uuu getitem\uuuu
。但是
defaultKey
应该从哪里来(它是参数?类的属性还是实例的属性?@jornsharpe是的,这是我的问题,如何实现它。我不知道如何在这种情况下使用ABCscontext@jonrsharpe是的,
defaultKey
是初始化时的参数,实例应将其存储为属性您继承它们,然后实现它们指定的方法(在本例中为
\u[get/set/del]item.\uuuu
\uuu iter.\uuuu
\uu len.\uuuu
,加上默认键值对的自定义
\uuu init.\uuuuu
。@jornsharpe我希望通过继承一个现成的对象(如
defaultdict
)并重写
\uu getitem.\uu>,可以让事情变得更简单,在其他任何地方都保留相同的功能…是的,这是可行的,但我需要创建一个默认情况下可以这样做的类,而无需在调用中显式指定它code@gt6989b那么,你的问题是什么?如果只是“我该怎么写呢?”那就太宽泛了。你是否尝试过创建一个继承
defaultdict
但覆盖
defaultfactory
方法的类?我同意Robert的观点。在这种情况下,创建自己的字典实现,并将其
.get()
覆盖到上述代码
defaultfactory
实际上会更改dict以获得新的内容
get
返回对现有对象的引用。所以,这取决于您想要什么…是的,这是可行的,但我需要创建一个默认情况下可以这样做的类,而无需在调用中显式指定它code@gt6989b那么,你的问题是什么?如果只是“我该怎么写呢?”那就太宽泛了。你是否尝试过创建一个继承
defaultdict
但覆盖
defaultfactory
方法的类?我同意Robert的观点。在这种情况下,创建自己的字典实现,并将其
.get()
覆盖到上述代码
defaultfactory
实际上会更改dict以获得新的内容
get
返回对现有对象的引用。所以取决于你想要什么…谢谢,我玩了一段时间,让它工作,不能做的权利。。。非常感谢你。如果我想按照您的建议在
\uuuuu init\uuuu()
中传递一个arg default\u键,那么签名将更改为
def\uuuuuu init\uuuu(self,default\u键,*args,**kwargs)
?或者我只是检查
default\u key
是否在
kwargs
中(如果是这样,我如何才能将其与字典中实际需要这样一对的人区分开来)?作为记录,规范的哨兵(因为
None
是一个有效值,因此不合适)就是执行
sentinel=object()
sentinel
可以
Null
如果你愿意,但我发现
sentinel
可以更直接地描述其用途)并与
is
进行所有比较(主要是为了效率;
对象的
\ueq\uu
无论如何都是身份检查)。无需创建相对昂贵的类来定义sentinel类型;
对象
可以直接构造以获得唯一的标记usi