【问题标题】:write json float in scientific notation用科学计数法写 json float
【发布时间】:2018-06-05 12:52:57
【问题描述】:

我想使用 Python 3.6+ 以科学计数法表示 JSON 文件中的浮点数。一个都没有

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))

工作:三个prints 都给了

0.001234567

而不是想要的

1.234567e-03

(请注意,最后一个版本至少在 Python 2.7.15rc1 中有效。)

答案也应该适用于floats 的列表。

有什么提示吗?

【问题讨论】:

标签: python json python-3.6


【解决方案1】:

您必须为字典、列表、集合等添加一些特殊的大小写,但是通过引用来自 collections.abc 的抽象基类,您可以避免显式测试特定类型。

请注意,Sequence 的测试必须避免匹配 str 类型,因为迭代 str 会产生一堆 1 字符 strs,它们也是可迭代的 Sequences,并且以此类推,直到达到递归限制。我找不到代表“序列容器,但不是 str”的 ABC。

(我还必须回应 Alex Martelli 在相关帖子中的批评,即必须做这么多工作来格式化特定类型,这说明了该模块中类的设计问题。)

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]]

【讨论】:

  • 感谢您的回答。这仅在转换 single 浮点数时有效。输入[a, a]就不行了。
  • 现在不适用于 dicts à la {"key": 0.00123}。如果所有案例都必须单独列出,这可能是一场艰苦的战斗。
  • 如果你可以使用来自collections.abc的抽象类型,也许不会那么糟糕
  • 关于重开的元讨论:meta.stackoverflow.com/q/369085/4909087
  • 这个答案的代码看起来略优于stackoverflow.com/a/1733105/6451573,这应该是这个问题的原始问题。我认为如果将其发布在此处会更有意义,并提供更多解释。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-04-04
  • 2020-03-10
  • 2011-07-18
  • 1970-01-01
相关资源
最近更新 更多