1

I have a piece of code that has creates a dictionary Enzyme_dict and then fills that dictionary with objects (from class Enzyme). One of the attributes of that class of objects is itself a dictionary (self._specif). The dictionary that makes up that attribute is filled up with several values, all equal to 1.0/5. Because of machine precision, this value gets printed as 0.20000000000000001, which makes printing a dictionary with many of these values unreadable.

I want to be able to write print Enzyme_dict and have it print all of the machine-rounded floating point values as .200 or something, instead of the unwieldy 0.20000000000000001. How can I do this?

When I try to format the __repr__ output within the class itself with %.3f, it tells me I can't do that because I'm trying to format a dictionary as a float (which makes sense). I would also like to keep those values that I'm trying to truncate as floats, and not turn them into strings.

I'm running python 2.6.6. Thank you for the help!

import random
random.seed(5)

numb_unique_chem = 10
numb_rxns = 10
numb_sub = 2
numb_prod = 2
E_pool_size_initial = 3 
numb_rxns_cat_initial = 5

class Enzyme(object):
    def __init__(self,rxns_cat,specif):
        self._rxns_cat = rxns_cat   
        self._specif = specif       
    def __repr__(self):
        return "Rxns catalyzed: %s, Specificity: %s \n" %(self._rxns_cat, self._specif)

Enzyme_dict = {}

R_pool_size = 10 # Rxn pool size, dictated by the input above
for ID in range(E_pool_size_initial):
    Enzyme_dict[ID] = Enzyme([],{}) 
    Enzyme_dict[ID]._rxns_cat = random.sample([n for n in range(10)],numb_rxns_cat_initial)

    Enzyme_dict[ID]._specif = {}
    for i in Enzyme_dict[ID]._rxns_cat:
        Enzyme_dict[ID]._specif[i] = (1.0/len(Enzyme_dict[ID]._rxns_cat))

print Enzyme_dict
Zero Piraeus
  • 56,143
  • 27
  • 150
  • 160
spacetyper
  • 1,471
  • 18
  • 27
  • 1
    Why not just iterate through the dictionary `.items()` and format and print each key/value pair yourself? – OdraEncoded May 16 '14 at 19:44
  • You don't want to format the *dictionary* as 3 d.p. `float`, you want to format its *values* that way. Also, `__repr__` shouldn't be used like that, use `__str__` - see http://stackoverflow.com/questions/1436703/difference-between-str-and-repr-in-python – jonrsharpe May 16 '14 at 19:47
  • 1
    I can't reproduce it in python 2.7.6: `python -c 'print repr(1.0/5)'` prints `0.2`. Is upgrading an option? (I would highly recommend it, 2.7.6 is a huge improvement.) You may also try to `round(1.0/len(Enzyme_dict[ID]._rxns_cat), 3)` – m.wasowski May 16 '14 at 19:54
  • @OdraEncoded I guess I don't have a good answer for that besides the fact that I was looking for simplicity. – spacetyper May 16 '14 at 19:56
  • @jonsharpe Right, so it seems to me I would have to change the 2nd-to-last line of code. I could format it as a string and have it print off the right number of decimals, but I would like to keep as a float if possible. Thanks for the note about `__str__` – spacetyper May 16 '14 at 20:00
  • @m.wasowski Hmm that's good to know. I will look into upgrading. On 2.6, using the round function like you suggested still gives `0.20000000000000001` – spacetyper May 16 '14 at 20:03
  • 1
    @m.wasowski it is indeed a change from 2.6 to 2.7: ["The repr() of a float x is shorter in many cases: it’s now based on the shortest decimal string that’s guaranteed to round back to x."](https://docs.python.org/2.7/whatsnew/2.7.html#python-3-1-features) – Zero Piraeus May 16 '14 at 20:51

1 Answers1

0

As OdraEncoded suggested, you can simply tweak your repr() method to print the following:

def __repr__(self):
        return "Rxns catalyzed: %s, Specificity: %s \n" %(self._rxns_cat, ['%.3f' % spec for spec in self._specif])
gilsho
  • 921
  • 7
  • 11