напишите json float в научной нотации - PullRequest
0 голосов
/ 05 июня 2018

Я хотел бы представлять числа с плавающей точкой в ​​файле JSON в научной нотации, используя Python 3.6+.Ни один из

import json

a = 0.001234567

print(json.dumps(a))

json.encoder.FLOAT_REPR = lambda x: "{:e}".format(x)
print(json.dumps(a))

json.encoder.c_make_encoder = None
json.encoder.FLOAT_REPR = lambda x: "{:e}".format(x)
print(json.dumps(a))

не работает: все три print s дают

0.001234567

вместо желаемого

1.234567e-03

(обратите внимание, что последняя версия работает наминимум в Python 2.7.15rc1.)

Ответ должен работать и со списками float с.

Есть подсказки?

1 Ответ

0 голосов
/ 05 июня 2018

Попробуй это.Вы должны добавить некоторые специальные регистры для диктовок, списков, наборов и т. Д., Но, ссылаясь на абстрактные базовые классы из collections.abc, вы избегаете явного тестирования на конкретные типы.

Обратите внимание, что тест для Sequence должен избегать сопоставления для типов str, поскольку итерация по str дает набор из 1 символа str s, которые также могут повторяться Sequences и так далее, пока не достигнете предела рекурсии.Я не смог найти ABC, который представляет «контейнер последовательности, но не str».

(Я также должен повторить критику Алекса Мартелли из соответствующего поста о том, что нужно проделать такую ​​большую работу только для форматированияопределенный тип говорит о проблемах в дизайне классов в этом модуле.)

import json
from collections.abc import Mapping, Sequence

a = 0.001234567

class ScientificNotationEncoder(json.JSONEncoder):
    def iterencode(self, o, _one_shot=False):
        if isinstance(o, float):
            return "{:e}".format(o)
        elif isinstance(o, Mapping):
            return "{{{}}}".format(', '.join('"{}" : {}'.format(str(ok), self.iterencode(ov))
                                             for ok, ov in o.items()))
        elif isinstance(o, Sequence) and not isinstance(o, str):
            return "[{}]".format(', '.join(map(self.iterencode, o)))
        return ', '.join(super().iterencode(o, _one_shot))

aout = json.dumps([a, a, "xyzzy", 42, {'z': a}, (a, a, a),],
                  cls=ScientificNotationEncoder)
print(aout)

# loading back in seems to still work okay!
print(json.loads(aout))

Отпечатки:

[1.234567e-03, 1.234567e-03, "xyzzy", 42, {"z" : 1.234567e-03}, [1.234567e-03, 1.234567e-03, 1.234567e-03]]
[0.001234567, 0.001234567, 'xyzzy', 42, {'z': 0.001234567}, [0.001234567, 0.001234567, 0.001234567]]
...