【问题标题】:How can i improve the readablility of nested if and for statements如何提高嵌套 if 和 for 语句的可读性
【发布时间】:2012-04-10 07:34:12
【问题描述】:

我有一段非常讨厌的代码我想重构,但因为它变得完全不可读。

 for region in feed['config']['regions']:
            if region['region'] == region_name:
                for instance_type in region['instanceTypes']:
                    if instance_type['type'] == instance_type_name:
                        for instance_size in instance_type['sizes']:
                            if instance_size['size'] == instance_size_name:
                                for platform in instance_size['valueColumns']:
                                    if platform['name'] == platform_name:
                                        prices = platform['prices']
                                        assert prices.keys() == ['USD']
                                        return decimal.Decimal(prices['USD'])
        assert False, "Failed to determine price for instance with region=%r, type=%r, size=%r, platform=%r" % \
                (region_name, instance_type_name, instance_size_name, platform_name)

我一直在为每个循环或 if 语句使用函数,但这会给我带来很多函数。 有更好的解决方案吗?

【问题讨论】:

  • 使用函数,所以你没有超过2个嵌套的for循环通常被认为是好的样式。 “大量函数”是一件好事(tm),特别是如果您使用文档字符串来记录它们:-)
  • @thebjorn 你的评论应该是一个答案

标签: python for-loop refactoring


【解决方案1】:
try:
    region = [r for r in feed['config']['regions'] if region['region'] == region_name][0]
    instance_type = [t for t in region['instanceTypes'] if i['type'] == instance_type_name][0]
    # ...
    return decimal.Decimal(prices['USD'])
except IndexError:
    raise Exception("Failed to determine price for instance with region=%r, type=%r, size=%r, platform=%r" % 
                (region_name, instance_type_name, instance_size_name, platform_name))

或者更进一步:

def filter_by_key(key, value, objects):
    return [o for o in objects if region[key] == value][0]

try:
    region = filter_by_key('region', region_name, feed['config']['regions'])
    instance_type = filter_by_key('type', instace_type_name, region['instanceTypes'])
    # ...
    return decimal.Decimal(prices['USD'])
except IndexError:
    raise Exception("Failed to determine price for instance with region=%r, type=%r, size=%r, platform=%r" % 
                (region_name, instance_type_name, instance_size_name, platform_name))

【讨论】:

    【解决方案2】:

    如果你想保持循环,你可以使用continue 来保存缩进:

    for region in feed['config']['regions']:
        if region['region'] != region_name: continue
        for instance_type in region['instanceTypes']:
            if instance_type['type'] != instance_type_name: continue
            for instance_size in instance_type['sizes']:
                if instance_size['size'] != instance_size_name: continue
                for platform in instance_size['valueColumns']:
                    if platform['name'] != platform_name: continue
                    prices = platform['prices']
                    assert prices.keys() == ['USD']
                    return decimal.Decimal(prices['USD'])
    assert False, "Failed to determine price for instance with region=%r, type=%r, size=%r, platform=%r" % \
                    (region_name, instance_type_name, instance_size_name, platform_name)
    

    或者使用列表推导:

    regions = (r for r in feed['config']['regions'] if r['region'] == region_name)
    instance_types = (i for i in r['instanceTypes'] for r in regions if i['type'] == instance_type_name)
    instance_sizes = (i for i in t['sizes'] for t in instance_types if i['size'] == instance_size_name)
    platforms = (p for p in s['valueColumns'] for s in instance_sizes if p['name'] == platform_name)
    for platform in platforms:
        prices = platform['prices']
        assert prices.keys() == ['USD']
        return decimal.Decimal(prices['USD'])
    assert False, "Failed to determine price for instance with region=%r, type=%r, size=%r, platform=%r" % \
                    (region_name, instance_type_name, instance_size_name, platform_name)      
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-02-20
      • 1970-01-01
      • 1970-01-01
      • 2014-05-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多