一个纯粹出于好奇心的问题.这显然是无效的语法:
foo = {}
foo['bar': 'baz']
Run Code Online (Sandbox Code Playgroud)
很明显发生了什么,开发人员从字典定义中移出一行,但没有将它从文字字典声明更改为赋值语法(并且已经适当地模拟了结果).
但我的问题是,为什么Python会TypeError: unhashable type
在这里而不是SyntaxError
?它试图散列的是什么类型?这样做:
'bar': 'baz'
Run Code Online (Sandbox Code Playgroud)
是一个SyntaxError,如下所示:
['bar': 'baz']
Run Code Online (Sandbox Code Playgroud)
所以我看不出什么类型的东西是不可用的.
mou*_*uad 21
我只是想为Ignacio的答案添加一些细节(这很棒)并且花了我一些时间来理解,对于像我这样没有得到它的人(我可能是唯一没有得到它的人,因为我没有看到有人问我不明白,但怎么知道:)):
我第一次想知道什么片?字典索引不接受切片?
但这是我的一个愚蠢的问题,因为我忘记了python是动态的(我多么愚蠢)所以当python编译代码时,第一次python不知道是否foo
是字典或列表所以它只是读取任何表达式像这个foo ['foo':'bar']作为切片,要知道你可以这样做:
def f():
foo = {}
foo['bar':'foo']
Run Code Online (Sandbox Code Playgroud)
通过使用dis模块,您将看到表达式'bar':'foo'
已自动转换为切片:
dis.dis(f)
2 0 BUILD_MAP 0
3 STORE_FAST 0 (foo)
3 6 LOAD_FAST 0 (foo)
9 LOAD_CONST 1 ('bar')
12 LOAD_CONST 2 ('foo')
15 SLICE+3 <<<<<<<<<<<<<<<<<<<<<< HERE!!!!!!
16 POP_TOP
17 LOAD_CONST 0 (None)
20 RETURN_VALUE
Run Code Online (Sandbox Code Playgroud)
在我第一次承认我没有想到这一点,我确实直接去了python的源代码试图理解为什么,因为__getitems__
列表不像__getitem__
字典,但现在我理解为什么因为如果它是一个切片和切片是不可取的它应该提高unhashable type
,所以这里是字典的代码__getitem__
:
static PyObject *
dict_subscript(PyDictObject *mp, register PyObject *key)
{
PyObject *v;
long hash;
PyDictEntry *ep;
assert(mp->ma_table != NULL);
if (!PyString_CheckExact(key) || // if check it's not a string
(hash = ((PyStringObject *) key)->ob_shash) == -1) {
hash = PyObject_Hash(key); // check if key (sliceobject) is hashable which is false
if (hash == -1)
return NULL;
}
....
Run Code Online (Sandbox Code Playgroud)
希望这可以帮助像我这样的人了解Ignacio的响应,对不起,如果我只是重复Ignacio的答案:)
归档时间: |
|
查看次数: |
1889 次 |
最近记录: |