Python 2.5中增加的collections.defaultdict极大地减少了对dict的setdefault方法的需求。这个问题是为了我们的集体教育:
在今天的Python 2.6/2.7中,setdefault在哪些方面仍然有用? setdefault的哪些流行用例被collections.defaultdict所取代?
Python 2.5中增加的collections.defaultdict极大地减少了对dict的setdefault方法的需求。这个问题是为了我们的集体教育:
在今天的Python 2.6/2.7中,setdefault在哪些方面仍然有用? setdefault的哪些流行用例被collections.defaultdict所取代?
当前回答
从理论上讲,如果您有时想设置默认值,有时不想设置默认值,那么setdefault仍然很方便。在现实生活中,我还没有遇到过这样的用例。
然而,一个有趣的用例来自标准库(Python 2.6, _threadinglocal.py):
>>> mydata = local()
>>> mydata.__dict__
{'number': 42}
>>> mydata.__dict__.setdefault('widgets', [])
[]
>>> mydata.widgets
[]
我会说使用__dict__。Setdefault是一个非常有用的例子。
编辑:碰巧,这是标准库中唯一的示例,并且它在注释中。因此,它可能不足以证明setdefault的存在。不过,这里有一个解释:
Objects store their attributes in the __dict__ attribute. As it happens, the __dict__ attribute is writeable at any time after the object creation. It is also a dictionary not a defaultdict. It is not sensible for objects in the general case to have __dict__ as a defaultdict because that would make each object having all legal identifiers as attributes. So I can't foresee any change to Python objects getting rid of __dict__.setdefault, apart from deleting it altogether if it was deemed not useful.
其他回答
Defaultdict在默认值是静态时很好,就像一个新列表,但如果它是动态的,就不那么好了。
例如,我需要一个字典来映射字符串到唯一的整数。Defaultdict (int)将始终使用0作为默认值。同样,defaultdict(intGen())总是生成1。
相反,我用了一个普通的词典:
nextID = intGen()
myDict = {}
for lots of complicated stuff:
#stuff that generates unpredictable, possibly already seen str
strID = myDict.setdefault(myStr, nextID())
注意这个词典。get(key, nextID())是不够的,因为我需要能够在以后引用这些值。
intGen是我构建的一个小类,它自动递增int并返回它的值:
class intGen:
def __init__(self):
self.i = 0
def __call__(self):
self.i += 1
return self.i
如果有人有办法做到这一点与defaultdict,我很乐意看到它。
我通常使用setdefault作为关键字参数字典,例如在这个函数中:
def notify(self, level, *pargs, **kwargs):
kwargs.setdefault("persist", level >= DANGER)
self.__defcon.set(level, **kwargs)
try:
kwargs.setdefault("name", self.client.player_entity().name)
except pytibia.PlayerEntityNotFound:
pass
return _notify(level, *pargs, **kwargs)
它非常适合在包装器中围绕接受关键字参数的函数调整参数。
正如Muhammad所说,在某些情况下,您只是偶尔希望设置默认值。一个很好的例子是数据结构,首先填充,然后查询。
考虑一个例子。在添加单词时,如果需要子节点但不存在,则必须创建子节点以扩展树。在查询单词是否存在时,缺少子节点表示该单词不存在,不应该创建它。
defaultdict不能这样做。相反,必须使用带有get和setdefault方法的常规dict。
我重写了公认的答案,并为新手提供了方便。
#break it down and understand it intuitively.
new = {}
for (key, value) in data:
if key not in new:
new[key] = [] # this is core of setdefault equals to new.setdefault(key, [])
new[key].append(value)
else:
new[key].append(value)
# easy with setdefault
new = {}
for (key, value) in data:
group = new.setdefault(key, []) # it is new[key] = []
group.append(value)
# even simpler with defaultdict
new = defaultdict(list)
for (key, value) in data:
new[key].append(value) # all keys have a default value of empty list []
另外,我将这些方法分类为参考:
dict_methods_11 = {
'views':['keys', 'values', 'items'],
'add':['update','setdefault'],
'remove':['pop', 'popitem','clear'],
'retrieve':['get',],
'copy':['copy','fromkeys'],}
defaultdict相对于dict (dict.setdefault)的一个缺点是,defaultdict对象每次给出不存在的键时都会创建一个新项(例如==,print)。此外,defaultdict类通常比dict类更不常见,它更难IME序列化。
注:IMO函数|方法不意味着改变对象,不应该改变对象。