【问题标题】:Why are these two distance-conversion methods creating different output?为什么这两种距离转换方法会产生不同的输出?
【发布时间】:2020-02-09 16:39:36
【问题描述】:

我正在尝试清理我编写的一些代码。该代码用于转换距离单位;例如,米到公里或秒差距到 AU。在下面的代码中,有两种实现;第一个实现是我在第二个实现中清理代码的失败尝试。第二个实现工作正常,但我试图在我的代码中使用更少的重复,同时仍然可读。

在下面的代码中,只转换了距离单位(我计划稍后添加其他类型的单位转换)。首先,单位的大小相对于一米进行缩放。由此确定所有其他单位转换(因为AU --> m 转换将是1000 倍于AU --> km 转换,其中10001 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))

我已经注释掉了第一种方法,因为它不起作用。运行上面的代码(使用第二种方法)会打印以下输出:

 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

我不明白这两种实现如何/为什么不同。我猜-假设它与字典理解计数元素的顺序有关。但我什至不确定这是否正确。有人可以帮我理解为什么这两种方法的输出不同吗?

【问题讨论】:

    标签: python-3.x dictionary numbers nested-loops dictionary-comprehension


    【解决方案1】:

    您的索引已关闭

    @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}" 
    

    .. 这只会在出现问题时发出输出

    【讨论】:

    • 谢谢,修复索引错误解决了我的问题。出于好奇,您认为这是解决此类问题的好方法,还是您会推荐其他方法?
    • @allthemike 如果版本 2 有效,我不会花时间做版本 1。 V2 更容易理解,在“更少的行”编码方面没有太多的“增益”——我可能会做一个真正的测试或使用断言而不是自己解析文本输出。见编辑。总而言之,我可能不会在这里使用实例方法 - 每次转换都会重新创建字典 throw away style。最好只创建一次(TL;DR:使用 None 创建类变量 dict,检查类 var 是否为 None,如果是,则创建 dict,否则只需使用它)。
    • @allthe V1 如果你之后调整单位会更好,因为你只需要编辑一个地方,而其他地方是从它计算出来的——这可能会让我这样做——通常你只需要虽然有一个转换 - 并且可以即时从“m”进行计算,而无需将它们持久化到自己的查找中 - 一如既往......这取决于:D
    猜你喜欢
    • 1970-01-01
    • 2022-12-05
    • 2023-04-11
    • 1970-01-01
    • 1970-01-01
    • 2019-07-20
    • 1970-01-01
    • 2021-10-07
    • 1970-01-01
    相关资源
    最近更新 更多