【问题标题】:How to round numeric output from yaml.dump, in Python?如何在 Python 中舍入来自 yaml.dump 的数字输出?
【发布时间】:2015-11-26 17:30:33
【问题描述】:

有没有一种干净的方法来控制yaml.dump 的数字舍入输出?例如,我有一个具有不同复杂性变量的类,其中一些是双精度数字,我想四舍五入到第 4 位。此yaml 输出仅用于显示;它不会被加载(即yaml.load不会被使用)。

作为一个简单的例子,考虑下面的 A 类:

import yaml
class A:
    def __init__(self):
        self.a = 1/7
        self.b = 'some text'
        self.c = [1/11, 1/13, 1/17, 'some more text']

    def __repr__(self):
        return yaml.dump(self)

A()

有输出

!!python/object:__main__.A
a: 0.14285714285714285
b: some text
c: [0.09090909090909091, 0.07692307692307693, 0.058823529411764705, some more text]

和期望的输出:

!!python/object:__main__.A
a: 0.1429
b: some text
c: [0.0909, 0.0769, 0.0588, some more text]

我想这可以通过yaml.representative 以某种干净的方式完成。 我想避免使用字符串 output 的舍入,因为实际的类结构可能更复杂(递归等)

【问题讨论】:

  • 我不知道你为什么不能只使用round(number, precision)
  • 类结构是动态的和复杂的(变量的数量可以改变)。它可以包含变量,这些变量本身就是其他变量的类。我认为这样做的一个干净的方法是定义一个代表,它识别双精度数字(floatarray.float)并在连接到dump 输出之前将它们四舍五入。这有意义吗?
  • 说实话,我不确定我是否理解你的代码。您可能需要发布比这更多的详细信息。但是,基本概念应该是您在类中找到一种方法来定义您想要的精度并将其与数字一起发送到函数round(number, precision)。要么就是这样,要么您需要定义另一个设置 precision 参数的条件,但是由于我完全不明白您要做什么,所以我无法告诉您如何定义该条件。
  • 让我知道什么看起来令人困惑。我很乐意澄清。我的代码应该在你的 Python 控制台中运行,产生第一个输出,但我需要第二个输出。不过,我不想使用round(a,4)round(b,4),...,因为变量可以改变。此类的另一个实例有变量xy。我认为四舍五入可以通过representative 方法合并到dump 本身中。这更清楚了吗?
  • @Y2H 代码使用pyyaml包序列化一个python类。

标签: python python-3.x yaml rounding precision


【解决方案1】:

您可以手动舍入:

#!/usr/bin/env python
import yaml

def float_representer(dumper, value):
    text = '{0:.4f}'.format(value)
    return dumper.represent_scalar(u'tag:yaml.org,2002:float', text)
yaml.add_representer(float, float_representer)

print(yaml.safe_dump([1 / 11, 1 / 13, 1 / 17, 'some more text']))
print(yaml.dump([1 / 11, 1 / 13, 1 / 17, 'some more text']))

输出

[0.09090909090909091, 0.07692307692307693, 0.058823529411764705, some more text]

[0.0909, 0.0769, 0.0588, some more text]

您可能需要为极端情况添加更多代码,请参阅 represent_float()@memoselyk suggested

【讨论】:

  • 效果很好。我只是想把这些放在一起(感谢@memoselyk),但你的意见很有价值。
  • @EmilyHill:你也可以使用text = '%.4f' % value(修复格式)。我没有使用它,因为我认为(it seems incorrectly)它使用了不同的rounding mode,但我目前找不到反例。
  • 所有很棒的建议!谢谢!
  • @EmilyHill:我进一步调查并发现我是对的:round()'%f' 可能会产生不同的结果,例如,f = 0.00635; print("{0:.4f} {1}".format(f, round(f, 4))) 在我的机器上的 Python 2.6 上打印 0.0063 0.0064 . Python 3应该没有区别。我已经更新了使用字符串格式的答案,以获得各种python版本的统一结果。
  • 有兴趣知道。感谢您的调查和帮助。
【解决方案2】:

为浮点数创建您自己的 repesenter,根据需要格式化浮点数,并将现有表示器替换为 yaml.add_representer(float, my_custom_repesenter)

Here 你可以找到浮点数的默认代表。您可以以该代码为起点,仅更改值不是[+-].inf.nan 的路径,然后将value 按摩到所需的精度。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-06-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-08-19
    • 1970-01-01
    • 2017-07-19
    相关资源
    最近更新 更多