让我们说
a = {1:2, 3:4, 5:6}
是否有内置函数(可能类似a.get2(7,5))
会返回a[7]
,或a[5]
如果a[7]
不存在?
这样的功能可以很容易地定义为a.get(val, a.get(def_key))
,但如果存在则更喜欢内置解决方案。
答案 0 :(得分:2)
你可以继承dict
:
class MyDict(dict):
def get2(self,*keys):
for k in keys:
if k in self:
return self.get(k)
return None # if not found
a = {1:2, 3:4, 5:6}
b = MyDict(a)
print(b.get2(2,10,5))
位置参数允许将行为扩展到n个键。一般情况下无法使用get
来了解密钥是否在dict中,因为某些值可能 None
因此in
测试。
避免使用 sentinel对象进行双dict测试
class MyDict(dict):
__notfound = object()
def get2(self,*keys):
for k in keys:
x = self.get(k,self.__notfound )
if x is not self.__notfound :
return x
return None # if not found
答案 1 :(得分:1)
可以设置常量回退值。一种方法是使用collections.defaultdict
。
请注意,这需要创建一个新词典。当然,我们可以分配给同一个变量。
from collections import defaultdict
a = {1:2, 3:4, 5:6}
a = defaultdict(lambda: a[5], a)
这会将默认值设置为常量6
,这将在找不到密钥时返回。如果需要,您每次更新a[5]
时都必须重置默认值。
答案 2 :(得分:1)
您可以定义dict的子类来访问具有虚拟默认值的字典条目,该默认值将应用于任何不存在的键,但在引用它们时实际上不会创建任何键(与setdefault()函数相反)< / p>
class dictWithDefault(dict):
def __init__(self,aDict={},defaultValue=None):
super().__init__(aDict)
def aFunction():pass
self._default = defaultValue if type(defaultValue) == type(aFunction) else lambda : defaultValue
def __getitem__(self,key):
return super().__getitem__(key) if key in self else self._default()
d = {1:2, 3:4, 5:6}
d = dictWithDefault(d,99)
d[1] # >>> 2
d[7] # >>> 99 this is the default value, but key 7 still doesn't exist
d[7] = 97
d[7] # >>> 97 once assigned the key has its own value
d._default = 100 # you can change the virtual default at any time
d[9] # >>> 100
d[8] += 5 # this can be useful when key/values are used to count things
# (using a default value of zero) akin to a Bag structure
d[8] # >>> 105
d # >>> {1: 2, 3: 4, 5: 6, 7: 97, 8: 105}
您也可以直接使用默认值创建字典:
d = dictWithDefault({1:2, 3:4, 5:6},99)
要使用默认密钥而不是默认值,您可以使用相同的技术,只需更改 getitem 方法的实现。
或者,您可以简单地使用d = dictWithDefault(d)而不使用默认值,并使用或运算符来获取替代密钥:
d = dictWithDefault(d)
value = d[7] or d[5]
[编辑] 更改了代码以支持对象作为默认值。
使用对象(例如列表)作为字典的值时,必须小心。在对新键的第一次隐式赋值时,它只会被赋予对_default对象的引用。这意味着所有这些键最终都会引用相同的对象。
例如:d = dictWithDefault(defaultValue = [])将无法按预期工作。
d = dictWithDefault(defaultValue=[])
d["A"].append(1)
d["B"].append(2)
# will end up with { "A":[1,2], "A":[1,2] }
# because both keys (A and B) reference the same list instance.
要解决这个问题,我更改了函数,以便接受lambda:在将对象用作默认值的情况下。
这允许默认值在用于新密钥时创建新实例。
d = dictWithDefault(defaultValue=lambda:[])
d["A"].append(1)
d["B"].append(2)
# now works properly giving: { "A":[1], "B":[2] }
对于简单类型(字符串,整数,...),您仍然可以使用没有lambda的类,但是当字典将对象存储为值时,您必须确保使用lambda:with instance creation方法。