Почему эти два метода преобразования расстояния создают разные результаты? - PullRequest
2 голосов
/ 12 октября 2019

Я пытаюсь очистить некоторый код, который я написал. Код используется для преобразования единиц расстояния;например, метры в километры или парсек в АС. В приведенном ниже коде есть две реализации;первая реализация - моя неудачная попытка очистить код во второй реализации. Вторая реализация работает правильно, но я пытаюсь использовать меньше повторений в своем коде, оставаясь читаемым.

В приведенном ниже коде конвертируются только единицы измерения расстояния (позже я планирую добавить другие типы единиц измерения). Сначала единицы масштабируются по размеру относительно одного метра. Исходя из этого, определяются все другие конверсии единиц (поскольку конверсии AU --> m будут в 1000 раз больше, чем конверсии AU --> km, где 1000 - это размер 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закомментировал первый метод, так как он не работает. Выполнение кода выше (с использованием второго метода) выводит следующий вывод:

 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

Если запустить первый метод (неправильный метод), товыводится следующий вывод:

 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

Я не вижу, как / почему эти две реализации различаются. Я предполагаю, что это имеет какое-то отношение к порядку, в котором словарь понимает элементы. Но яЯ даже не уверен, что это правильно. Может ли кто-нибудь помочь мне понять, почему эти два метода не имеют одинакового вывода?

1 Ответ

2 голосов
/ 12 октября 2019

Ваша индексация выключена

@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]   # outer_key here 
                              for inner_key, value in res['m'].items()}
    return res

Использование:

@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'][outer_key] 
                              for inner_key, value in res['m'].items()}
    return res

с:

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)
        print('{} {} = {} {}'.format(distance, original_unit, res, prime_unit), 
              end = " ..... ")
        res = UC.second_convert_distance(distance, original_unit, prime_unit)
        print('{} {} = {} {}'.format(distance, original_unit, res, prime_unit))

отпечатков:

5 m = 5 m ..... 5 m = 5 m
5 m = 0.005 km ..... 5 m = 0.005 km
5 m = 3.342245989304813e-11 AU ..... 5 m = 3.342245989304813e-11 AU
5 m = 5.284853609555015e-16 LY ..... 5 m = 5.284853609555015e-16 LY
5 m = 1.6202203499675955e-16 pc ..... 5 m = 1.6202203499675955e-16 pc
5 km = 5000 m ..... 5 km = 5000 m
5 km = 5.0 km ..... 5 km = 5.0 km
5 km = 3.342245989304813e-08 AU ..... 5 km = 3.342245989304813e-08 AU
5 km = 5.284853609555016e-13 LY ..... 5 km = 5.284853609555016e-13 LY
5 km = 1.6202203499675955e-13 pc ..... 5 km = 1.6202203499675955e-13 pc
5 AU = 748000000000.0 m ..... 5 AU = 748000000000.0 m
5 AU = 748000000.0 km ..... 5 AU = 748000000.0 km
5 AU = 5.0 AU ..... 5 AU = 5.0 AU
5 AU = 7.906140999894303e-05 LY ..... 5 AU = 7.906140999894303e-05 LY
5 AU = 2.4238496435515228e-05 pc ..... 5 AU = 2.4238496435515228e-05 pc
5 LY = 4.7305e+16 m ..... 5 LY = 4.7305e+16 m
5 LY = 47305000000000.0 km ..... 5 LY = 47305000000000.0 km
5 LY = 316209.89304812835 AU ..... 5 LY = 316209.89304812835 AU
5 LY = 5.0 LY ..... 5 LY = 5.0 LY
5 LY = 1.5328904731043422 pc ..... 5 LY = 1.5328904731043422 pc
5 pc = 1.543e+17 m ..... 5 pc = 1.543e+17 m
5 pc = 154300000000000.0 km ..... 5 pc = 154300000000000.0 km
5 pc = 1031417.1122994652 AU ..... 5 pc = 1031417.1122994652 AU
5 pc = 16.309058239086777 LY ..... 5 pc = 16.309058239086777 LY
5 pc = 5.0 pc ..... 5 pc = 5.0 pc

Вероятно, лучше для тестирования (если вы не пишете настоящие тесты):

for original_unit in UC.base_units:
    for prime_unit in UC.base_units:
        m1 = UC.first_convert_distance(distance, original_unit, prime_unit)
        m2 = UC.second_convert_distance(distance, original_unit, prime_unit)
        assert m1 == m2, f"{m1} != {m2} for {original_unit} to {prime_unit}" 

.. это выдаст вывод, только если что-то не так

...