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

Почему json.dumps(list (np.arange(5))) сбой, тогда как json.dumps(np.arange(5).tolist()) работает

Я заметил эту проблему, когда недавно был обновлен компьютер с Ubuntu, а версия Python по умолчанию изменилась на 2.7.

import json
import numpy as np

json.dumps(list(np.arange(5))) # Fails, throws a "TypeError: 0 is not JSON serializable"
json.dumps(np.arange(5).tolist()) # Works 

Есть ли разница между list() и tolist() metd массива numpy?

4b9b3361

Ответ 1

Похоже, что метод tolist() возвращает numpy int32 (или любой другой размер) обратно в int, что JSON знает, что делать с:

>>> list(np.arange(5))
[0, 1, 2, 3, 4]
>>> type(list(np.arange(5)))
<type 'list'>
>>> type(list(np.arange(5))[0])
<type 'numpy.int32'>
>>> np.arange(5).tolist()
[0, 1, 2, 3, 4]
>>> type(np.arange(5).tolist())
<type 'list'>
>>> type(np.arange(5).tolist()[0])
<type 'int'>

Как говорят документы для tolist():

Возвращает массив как (возможно, вложенный) список.

Возвращает копию данных массива в виде (вложенного) списка Python. Элементы данных преобразуются в ближайший совместимый тип Python.

Последняя строка имеет здесь значение.

Ответ 2

Поскольку элементы массива NumPy не являются родными ints, а являются собственными типами NUmPy:

>>> type(np.arange(5)[0])
<type 'numpy.int64'>

Вы можете использовать JSONEncoder для поддержки типа ndarray, возвращаемого arange:

import numpy as np
import json

class NumPyArangeEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, np.ndarray):
            return obj.tolist() # or map(int, obj)
        return json.JSONEncoder.default(self, obj)

print(json.dumps(np.arange(5), cls=NumPyArangeEncoder))

Ответ 3

Проблема в том, что с первой вы не получите int. Вы получаете numpy.int64. Это не может быть сериализовано.