список литерала и список понимания, ведущие себя по-разному - PullRequest
0 голосов
/ 26 мая 2019

У меня очень странная проблема с Python 3.7. В частности, у меня есть функция, которая берет список идентификаторов документов и возвращает документы википедии, которым они соответствуют. Странно то, что, если я передаю понимание списка, как я хочу, он ничего не возвращает, но если я передаю литерал списка с точно такими же значениями, он как-то работает. Обратите внимание, что это использует pdb, в интерактивной подсказке он открывается при вводе interact:

Если я запускаю понимание списка, я получаю этот список:

>>> [x[0] for x in truncated]
[3553957, 4480571, 4686346, 1955046, 4476254, 4510002, 3941950, 2991560, 5314256, 3949007]

Если я запускаю запрос с этим литералом списка, он работает (данные для краткости усечены):

>>> self._db.query_ids([3553957, 4480571, 4686346, 1955046, 4476254, 4510002, 3941950, 2991560, 5314256, 3949007])
[(1955046, 'Hairy_nightshade', 'Hairy nightshade is a common name for...')]

Но если я объединю два выражения, ничего не получится:

>>> self._db.query_ids([x[0] for x in truncated])
[]

Реальная вызываемая функция не имеет побочных эффектов, она просто запрашивает базу данных, поэтому она не изменяется между вызовами:

def query_ids(self, ids):
    """
    Returns the tokens for each document with the given ID
    """
    result = self.conn.execute(
        'SELECT doc_id, document, group_concat(tokens, " ") FROM doc WHERE doc_id in ({}) GROUP BY doc_id'.format(
            ', '.join(['?'] * len(ids))), ids)
    data = result.fetchall()
    return data

Как это возможно?


Если я добавлю print(ids) в первую строку моей функции query_ids, список идентификаторов будет напечатан одинаково оба раза, но он все равно не будет работать с пониманием списка:

(Pdb) self._db.query_ids([x[0] for x in truncated])
[3553957, 4480571, 4686346, 1955046, 4476254, 4510002, 3941950, 2991560, 5314256, 3949007]
[]
(Pdb) self._db.query_ids([3553957, 4480571, 4686346, 1955046, 4476254, 4510002, 3941950, 2991560, 5314256, 3949007])
[3553957, 4480571, 4686346, 1955046, 4476254, 4510002, 3941950, 2991560, 5314256, 3949007]
[(1955046, 'Hairy_nightshade', 'Hairy nightshade is a common name for several plants and may refer to...')]

1 Ответ

2 голосов
/ 26 мая 2019

Это была странная ошибка, но я думаю, что исправил ее.

Проблема была не в типе truncated, который представлял собой список, а скорее в том, что содержимое этого списка представляло собой целые числа типа int64, не целые числа Python:

(Pdb) !a = [x[0] for x in truncated]
(Pdb) type(a)
<class 'list'>
(Pdb) type(a[0])
<class 'numpy.int64'>

Когда этот список numpy.int64 s был передан в запрос к базе данных, он был проигнорирован, поскольку API Python sqlite3 не знает, как обращаться с не родными типами Python: https://docs.python.org/3/library/sqlite3.html#using-adapters-to-store-additional-python-types-in-sqlite-databases

Таким образом, следующие типы Python могут быть отправлены в SQLite без проблем: None, int, float, str, bytes

Таким образом, когда я преобразовал данные в родные числа Python, это сработало:

(Pdb) self._db.query_ids([int(x[0]) for x in truncated])
[3553957, 4480571, 4686346, 1955046, 4476254, 4510002, 3941950, 2991560, 5314256, 3949007]
[(1955046, 'Hairy_nightshade', 'Hairy nightshade is a common name for several plants and may refer to ')]
...