从here找到的递归字典的解决方案中,我看到了以下Python食谱:
class RecursiveDict(dict):
"""Implementation of perl's autovivification feature."""
def __missing__(self, key):
value = self[key] = type(self)()
return value关于value = self[key] = type(self)()这一行:与下面的代码相比,它有什么优点或缺点?或者仅仅是语法问题?
self[key] = type(self)()
value = self[key]发布于 2013-02-28 06:04:02
它主要是语法糖,但不是针对您列出的语句;相反,它等同于
value = type(self)()
self[key] = value要查看差异,请在Python提示符下键入以下内容:
>>> class FakeDict(object):
... def __setitem__(self, k, v):
... pass
... def __getitem__(self, k):
... raise KeyError("boom!")
...
>>> d = FakeDict()
>>> x = d[1] = 42
>>> d[1] = 42
>>> x = d[1]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 5, in __getitem__
KeyError: boom!当然,对于行为良好的dict,这并不重要,但是
self[key] = type(self)()
value = self[key]不会在第二行执行多余的dict查找,因此在循环中,速记可能会带来性能优势。
在一般的情况下,,它甚至比我上面所说的还要复杂一点。速记赋值实际上等同于
__some_temporary = type(self)()
value = __some_temporary
self[key] = __some_temporary只有因为value是一个简单的局部变量,才会出现简化形式的value = type(self)(); self[key] = value。如果将value替换为可能失败的container[key]形式的表达式,等价性将不再有效。
发布于 2013-02-28 06:01:08
它只是一个语法。有时它会使代码更容易阅读,有时却不会。
但是会发生什么呢?另一个答案让我感到好奇:我对它进行了评论,说compier可能使用了“寄存器或变量”,而这正是发生的事情。让我们反编译一个简单的函数:
>>> import dis
>>> def f():
... a = b = c = 1
... return a
...
>>> dis.dis(f)
2 0 LOAD_CONST 1 (1)
3 DUP_TOP
4 STORE_FAST 0 (a)
7 DUP_TOP
8 STORE_FAST 1 (b)
11 STORE_FAST 2 (c)
3 14 LOAD_FAST 0 (a)
17 RETURN_VALUE 最右边的值(在我的例子中是type(self)() )被加载到堆栈(考虑“局部变量”),然后复制到堆栈(在基于堆栈的VM操作中消耗堆栈,所以如果你想“保留”一个值,你需要制作多个副本),然后赋值,然后复制,然后赋值,依此类推。也就是说,转换回Python。这类似于:
def f():
t = 1
a = t
b = t
c = t
return a编译器甚至保留了赋值从左到右的顺序(a,b,c)。
https://stackoverflow.com/questions/15123267
复制相似问题