比方说
a = {1:2, 3:4, 5:6}
有没有内置函数(可能是类似a.get2(7,5))
的函数,返回a[7]
;如果a[7]
不存在,则返回a[5]
?)
这类函数可以很容易地定义为a.get(val, a.get(def_key))
,但如果存在,则更倾向于使用内置解决方案。
发布于 2018-03-22 18:24:09
您可以子类化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
来知道关键字是否在字典中,因为一些值可能为None
,因此需要进行in
测试。
避免使用sentinel对象进行双重判定测试
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
发布于 2018-03-22 18:18:54
可以设置常量回退值。一种方法是使用collections.defaultdict
。
注意:这需要创建一个新的字典。当然,我们可以将其赋给相同的变量。
from collections import defaultdict
a = {1:2, 3:4, 5:6}
a = defaultdict(lambda: a[5], a)
这会将默认值设置为常量6
,该常量将在找不到密钥时返回。如果需要,您必须在每次更新a[5]
时重置您的默认值。
发布于 2018-03-23 08:53:30
您可以定义dict的子类来访问具有虚拟默认值的字典条目,该值将应用于任何不存在的键,但在引用它们时不会实际创建任何键(与setdefault()函数相反)
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:与实例创建方法一起使用。
https://stackoverflow.com/questions/49425941
复制相似问题