I am trying to clean up some code I wrote. The code is used to convert distance units; for example, meters to kilometers or parsecs to AU. In the code below, there are two implementations; the first implementation is my failed attempt to clean up the code in the second implementation. The second implementation works correctly, but I'm trying to use less repetition in my code while still being readable.
In the code below, only distance units are converted (I plan to add other types of unit conversions later). First, the units are scaled in size relative to one meter. From this, all other unit conversions are determined (since AU --> m conversions will be 1000 times greater than AU --> km conversions, where 1000 is the size of 1 km / 1 m.
class UnitConversions():
def __init__(self):
self.base_units = ('m', 'km', 'AU', 'LY', 'pc')
self.base_values = (1, 1000, 1.496e11, 9.461e15, 3.086e16)
@property
def first_distance_conversion_factors(self):
res = {}
res['m'] = dict(zip(self.base_units, self.base_values))
for outer_key in self.base_units:
if outer_key != 'm':
res[outer_key] = {inner_key : value / res['m'][inner_key] for inner_key, value in res['m'].items()}
return res
@property
def second_distance_conversion_factors(self):
""" """
res = {}
res['m'] = {'m' : 1, 'km' : 1000, 'AU' : 1.496e11, 'LY' : 9.461e15, 'pc' : 3.086e16}
res['km'] = {key : value / res['m']['km'] for key, value in res['m'].items()}
res['AU'] = {key : value / res['m']['AU'] for key, value in res['m'].items()}
res['LY'] = {key : value / res['m']['LY'] for key, value in res['m'].items()}
res['pc'] = {key : value / res['m']['pc'] for key, value in res['m'].items()}
return res
def first_convert_distance(self, distance, original_unit, prime_unit='m'):
""" """
conversion_factor = self.first_distance_conversion_factors[prime_unit][original_unit]
return distance * conversion_factor
def second_convert_distance(self, distance, original_unit, prime_unit='m'):
""" """
conversion_factor = self.second_distance_conversion_factors[prime_unit][original_unit]
return distance * conversion_factor
UC = UnitConversions()
distance = 5
for original_unit in UC.base_units:
for prime_unit in UC.base_units:
# res = UC.first_convert_distance(distance, original_unit, prime_unit)
res = UC.second_convert_distance(distance, original_unit, prime_unit)
print('\n {} {} = {} {}'.format(distance, original_unit, res, prime_unit))
I have commented out the first method since it does not work. Running the code above (using the second method) prints the following output:
5 m = 5 m
5 m = 0.005 km
5 m = 3.342245989304813e-11 AU
5 m = 5.284853609555015e-16 LY
5 m = 1.6202203499675955e-16 pc
5 km = 5000 m
5 km = 5.0 km
5 km = 3.342245989304813e-08 AU
5 km = 5.284853609555016e-13 LY
5 km = 1.6202203499675955e-13 pc
5 AU = 748000000000.0 m
5 AU = 748000000.0 km
5 AU = 5.0 AU
5 AU = 7.906140999894303e-05 LY
5 AU = 2.4238496435515228e-05 pc
5 LY = 4.7305e+16 m
5 LY = 47305000000000.0 km
5 LY = 316209.89304812835 AU
5 LY = 5.0 LY
5 LY = 1.5328904731043422 pc
5 pc = 1.543e+17 m
5 pc = 154300000000000.0 km
5 pc = 1031417.1122994652 AU
5 pc = 16.309058239086777 LY
5 pc = 5.0 pc
If one runs the first method (the incorrect method), then the following output is printed:
5 m = 5 m
5 m = 5.0 km
5 m = 5.0 AU
5 m = 5.0 LY
5 m = 5.0 pc
5 km = 5000 m
5 km = 5.0 km
5 km = 5.0 AU
5 km = 5.0 LY
5 km = 5.0 pc
5 AU = 748000000000.0 m
5 AU = 5.0 km
5 AU = 5.0 AU
5 AU = 5.0 LY
5 AU = 5.0 pc
5 LY = 4.7305e+16 m
5 LY = 5.0 km
5 LY = 5.0 AU
5 LY = 5.0 LY
5 LY = 5.0 pc
5 pc = 1.543e+17 m
5 pc = 5.0 km
5 pc = 5.0 AU
5 pc = 5.0 LY
5 pc = 5.0 pc
I don't see how/why the two implementations are different. I'm guess-assuming that it has something to with the order that dictionary comprehensions count elements. But I'm not even sure if this is correct. Can someone help me understand why these two methods do not have the same output?