Eli*_*sky 181 python dictionary setdefault
加入collections.defaultdict在Python 2.5大大降低用于需要dict的setdefault方法.这个问题适合我们的集体教育:
setdefault今天在Python 2.6/2.7中还有什么用处?setdefault被取代了collections.defaultdict?Joc*_*zel 194
你可以说defaultdict是设置默认有用填充字典之前和setdefault是设置默认值有用,同时或填充字典之后.
可能是最常见的用例:分组项目(未分类数据,否则使用itertools.groupby)
# really verbose
new = {}
for (key, value) in data:
if key in new:
new[key].append( value )
else:
new[key] = [value]
# easy with setdefault
new = {}
for (key, value) in data:
group = new.setdefault(key, []) # key might exist already
group.append( value )
# even simpler with defaultdict
new = defaultdict(list)
for (key, value) in data:
new[key].append( value ) # all keys have a default already
Run Code Online (Sandbox Code Playgroud)
有时您希望在创建dict后确保存在特定键.defaultdict在这种情况下不起作用,因为它只在显式访问时创建密钥.认为你使用HTTP-ish和许多标题 - 有些是可选的,但你想要它们的默认值:
headers = parse_headers( msg ) # parse the message, get a dict
# now add all the optional headers
for headername, defaultvalue in optional_headers:
headers.setdefault( headername, defaultvalue )
Run Code Online (Sandbox Code Playgroud)
Mat*_*ner 28
我通常setdefault用于关键字参数dicts,例如在这个函数中:
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)
Run Code Online (Sandbox Code Playgroud)
在包含关键字参数的函数的包装器中调整参数是很好的.
Dav*_*rek 15
defaultdict 当默认值是静态时(例如新列表)很好,但如果它是动态的则不是很好.
例如,我需要一个字典来将字符串映射到唯一的int.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())
Run Code Online (Sandbox Code Playgroud)
请注意,这dict.get(key, nextID())是不够的,因为我需要稍后能够引用这些值.
intGen 是我构建的一个小类,它自动递增一个int并返回它的值:
class intGen:
def __init__(self):
self.i = 0
def __call__(self):
self.i += 1
return self.i
Run Code Online (Sandbox Code Playgroud)
如果有人有办法做到这一点,defaultdict我很乐意看到它.
pic*_*e 涅 14
正如大多数答案所述,setdefault或者defaultdict让您在键不存在时设置默认值。但是,我想指出一个关于setdefault. 当 Python 解释器执行时setdefault,即使键存在于字典中,它也会始终评估函数的第二个参数。例如:
In: d = {1:5, 2:6}
In: d
Out: {1: 5, 2: 6}
In: d.setdefault(2, 0)
Out: 6
In: d.setdefault(2, print('test'))
test
Out: 6
Run Code Online (Sandbox Code Playgroud)
如您所见,print即使字典中已经存在 2 也被执行。如果您计划将其setdefault用于诸如memoization. 如果将递归函数调用添加为 的第二个参数setdefault,则不会从中获得任何性能,因为 Python 将始终以递归方式调用该函数。
由于提到了记忆化,如果您考虑使用记忆化增强功能,更好的选择是使用 functools.lru_cache 装饰器。lru_cache 更好地处理递归函数的缓存要求。
正如穆罕默德所说,在某些情况下,您有时只希望设置默认值.一个很好的例子是首先填充,然后查询的数据结构.
考虑一个特里.添加单词时,如果需要子节点但不存在,则必须创建子节点以扩展trie.在查询单词的存在时,缺少的子节点表示该单词不存在且不应创建.
defaultdict无法执行此操作.相反,必须使用带有get和setdefault方法的常规字典.
从理论上讲,setdefault如果你有时想要设置默认值而有时不设置默认值,那么仍然会很方便.在现实生活中,我没有遇到过这样的用例.
但是,一个有趣的用例来自标准库(Python 2.6,_threadinglocal.py):
>>> mydata = local()
>>> mydata.__dict__
{'number': 42}
>>> mydata.__dict__.setdefault('widgets', [])
[]
>>> mydata.widgets
[]
Run Code Online (Sandbox Code Playgroud)
我会说使用__dict__.setdefault是一个非常有用的案例.
编辑:碰巧,这是标准库中唯一的例子,它在评论中.因此,证明存在的合理性可能还不够setdefault.不过,这里有一个解释:
对象将其属性存储在__dict__属性中.实际上,该__dict__属性在对象创建后的任何时候都是可写的.它也是一本字典而不是一本defaultdict.对于一般情况下的对象而言,将其__dict__作为defaultdict因为将使每个对象具有所有合法标识符作为属性是不明智的.所以我无法预见Python对象的任何变化__dict__.setdefault都会被删除,除非它被认为是无用的完全删除它.
| 归档时间: |
|
| 查看次数: |
91389 次 |
| 最近记录: |