我想创建一个python字典,它返回字典中缺少键的键值。
用法示例:
dic = smart_dict()
dic['a'] = 'one a'
print(dic['a'])
# >>> one a
print(dic['b'])
# >>> b
答案 0 :(得分:59)
dict
有一个__missing__
钩子:
class smart_dict(dict):
def __missing__(self, key):
return key
答案 1 :(得分:24)
为什么不使用
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^object attribute '__missing__' is read-only
,所以你必须继承:
from collections import defaultdict
class KeyDict(defaultdict):
def __missing__(self, key):
return key
d = KeyDict()
print d['b'] #prints 'b'
print d.keys() #prints []
答案 2 :(得分:13)
第一位回应者提到defaultdict
,
但您可以为__missing__
的任何子类定义dict
:
>>> 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'
答案 3 :(得分:6)
恭喜。你也发现了无用的东西
标准collections.defaultdict
类型。如果code smell那个可执行的midden堆
像我一样冒犯你敏感的感情,这是你的幸运
StackOverflow日。
感谢type()
collections.defaultdict
的禁忌
内置,制作一个非无用的默认字典类型既有趣又有利可图。
绝对没有,假设你喜欢过多的样板和dict
的令人震惊的愚蠢 - 应该按预期行事,但实际上并非如此。公平地说,3-parameter
variant Jochen
Ritzel的子类DefaultDict
和accepted
solution
实施optional __missing__()
method 是太棒了
小规模用例的解决方法,只需要一个默认字典。
但这种样板很难扩展。如果你发现自己实例化了 多个默认词典,每个词典都有自己略有不同的逻辑 产生缺失的键值对,一种工业强度的替代品 自动化样板是有保证的。
或者至少很好。因为为什么不修理破碎的东西?
不到十行的纯Python(不包括docstrings,comments和
我们现在定义一个用用户定义初始化的collections.defaultdict
类型
可调用生成缺失键的默认值。而可赎回通过了
标准DefaultDict
类型无用地接受否
参数,传递给我们的>>> dic = DefaultDict(lambda self, missing_key: missing_key)
>>> dic['a'] = 'one a'
>>> print(dic['a'])
one a
>>> print(dic['b'])
b
类型的可调用有用地接受
以下两个参数:
鉴于此类型,解决sorin的问题 问题缩减为单行Python:
def DefaultDict(keygen):
'''
Sane **default dictionary** (i.e., dictionary implicitly mapping a missing
key to the value returned by a caller-defined callable passed both this
dictionary and that key).
The standard :class:`collections.defaultdict` class is sadly insane,
requiring the caller-defined callable accept *no* arguments. This
non-standard alternative requires this callable accept two arguments:
#. The current instance of this dictionary.
#. The current missing key to generate a default value for.
Parameters
----------
keygen : CallableTypes
Callable (e.g., function, lambda, method) called to generate the default
value for a "missing" (i.e., undefined) key on the first attempt to
access that key, passed first this dictionary and then this key and
returning this value. This callable should have a signature resembling:
``def keygen(self: DefaultDict, missing_key: object) -> object``.
Equivalently, this callable should have the exact same signature as that
of the optional :meth:`dict.__missing__` method.
Returns
----------
MappingType
Empty default dictionary creating missing keys via this callable.
'''
# Global variable modified below.
global _DEFAULT_DICT_ID
# Unique classname suffixed by this identifier.
default_dict_class_name = 'DefaultDict' + str(_DEFAULT_DICT_ID)
# Increment this identifier to preserve uniqueness.
_DEFAULT_DICT_ID += 1
# Dynamically generated default dictionary class specific to this callable.
default_dict_class = type(
default_dict_class_name, (dict,), {'__missing__': keygen,})
# Instantiate and return the first and only instance of this class.
return default_dict_class()
_DEFAULT_DICT_ID = 0
'''
Unique arbitrary identifier with which to uniquify the classname of the next
:func:`DefaultDict`-derived type.
'''
理智。 最后。
type()
键 ...得到它,键? 到这个神秘的魔法是调用
3-parameter variant
内置type(default_dict_class_name, (dict,), {'__missing__': keygen,})
的内容:
dict
这一行动态地生成一个新的__missing__
子类别名
调用者定义的可调用的可选DefaultDict
方法。注意截然不同
缺少样板,将@Override
public void onCompletion(MediaPlayer mediaPlayer) {
if (isShuffle) {
if (intent.hasExtra("songIndex")) {
Random random = new Random();
songIndex = random.nextInt((songList.size() - 1) + 1);
playSongWithIndex(songIndex);
}
}
}
用法减少到单行Python。
极度胜利的自动化。
答案 4 :(得分:1)
我同意这应该很容易做到,也很容易设置不同的默认值或函数,以某种方式转换缺失值。
受到Cecil Curry answer的启发,我问自己:为什么不将默认生成器(常量或可调用的)作为类的成员,而不是生成不同的班级一直在吗?让我演示一下:
# 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
并将其逻辑吸收到__init__
。
可以在两个额外的行中添加对当前(常量)默认值的内省。
答案 5 :(得分:0)
子类dict
的{{1}}方法。例如,How to properly subclass dict and override __getitem__ & __setitem__