Подтвердить что ты не робот

Почему Python повышает TypeError, а не SyntaxError?

Вопрос исключительно ради любопытства. Это явно недействительный синтаксис:

foo = {}
foo['bar': 'baz']

Очевидно, что произошло, разработчик переместил строку из определения словаря, но не изменил ее из словарного словаря в синтаксис присваивания (и в результате был соответствующим образом изделен).

Но мой вопрос: почему Python поднимает TypeError: unhashable type здесь, а не SyntaxError? Какого типа он пытается хешировать? Просто выполните это:

'bar': 'baz'

- это SyntaxError, как это:

['bar': 'baz']

поэтому я не вижу, какой тип создается, который не сотрясается.

4b9b3361

Ответ 1

Использование двоеточия в операции индексирования генерирует объект slice, который не является хешируемой.

Ответ 2

Я просто хочу добавить некоторые детали к Ответу Игнасио (это здорово), и мне потребуется некоторое время, чтобы понять, и для таких людей, как я, которые не получили это (я могу быть единственным, кто этого не понимал, потому что я не видел, чтобы кто-то спрашивал, что я не понял, но как знает:)):

в первый раз, когда я задаюсь вопросом, какой ломтик? индексирование слова не принимает разрезание?

но это глупый вопрос с моей стороны, потому что я забыл, что python является динамическим (как глупый я), поэтому, когда python компилирует код, кустарный python не знает, есть ли foo словарь или список поэтому он просто читает любое выражение, подобное этому foo ['foo': 'bar'] как срез, чтобы знать, что вы можете просто сделать:

def f():
    foo = {}
    foo['bar':'foo']

и используя 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   

в первый раз, я признаю, что не думал об этом, и я пошел прямо к исходному коду 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 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;
    } 
    ....

Надеюсь, это поможет некоторым людям, как я, понять великий ответ Игнасио, и извините, если я просто дублирую ответ Игнасио:)