Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to round numeric output from yaml.dump, in Python?

Is there a clean way to control number rounding output of yaml.dump? For example, I have a class with different complexity variables, some of which are double precision numbers I want to be round to say 4th digit. This yaml output is for display only; it will not be loaded (i.e. yaml.load will not be used).

As a naive example, consider class A below:

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

with output

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

and desired output:

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

I suppose this can be done with yaml.representative in some clean way. I'd like to avoid using rounding of string output, because the actual class structure can be more complex (recursive, etc.)

like image 729
Oleg Melnikov Avatar asked Oct 15 '25 23:10

Oleg Melnikov


2 Answers

You could round it manually:

#!/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']))

Output

[0.09090909090909091, 0.07692307692307693, 0.058823529411764705, some more text]

[0.0909, 0.0769, 0.0588, some more text]

You might need to add more code for corner-cases, see represent_float() as @memoselyk suggested.

like image 156
jfs Avatar answered Oct 17 '25 13:10

jfs


Create your own repesenter for floats that formats the float numbers as you desire, and replace the existing representer with yaml.add_representer(float, my_custom_repesenter).

Here you can find the default representer for floats. You can take that code as an starting point and only change the path where value is not [+-].inf or .nan, and massage the value into your desired precision.

like image 33
memoselyk Avatar answered Oct 17 '25 14:10

memoselyk



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!