Python初学者——如何清理这段代码

2 投票
1 回答
1159 浏览
提问于 2025-04-18 02:54

这是我从零开始编写的第一个Python脚本的一部分。完整的代码是为了处理一些珠子,用于珠子工艺项目,并评估某些设计模式是否可行。代码是可以运行的,我用pylint检查过,分数超过了9.5,但有人告诉我“number_selection”这个函数分支太多,我希望能得到一些帮助来简化它。我知道一定有简单的方法可以让这段代码变得不那么冗长,去掉我所有的if语句,但我现在有点无从下手。

顺便提一下,“beads”是一个全局变量,是通过raw_input提供的。

任何建议都很感激。谢谢大家的帮助。

def number_suggestion():
''' if number entered does not work, then find the closest 
usable numbers, figure out which number provides the greatest 
number of design options and suggest that number. 
'''
next_lower = beads
next_higher = beads
list1 = []
list2 = []
add_one = 1    

# find next usable next_lower bead number
while next_lower >= 12 and next_lower % 6 != 0 and \
next_lower % 9 != 0 and next_lower % 12 != 0:
    next_lower -= 1
# find next usable next_higher bead number
while next_higher >= 12 and next_higher % 6 != 0 and \
next_higher % 9 != 0 and next_higher % 12 != 0:
    next_higher += 1

# add elements to list while counting to next usable number   
if next_lower >= 12 and next_lower % 6 == 0:
    list1.append(add_one)
if next_lower > 12 and next_lower % 9 == 0:
    list1.append(add_one)
if next_lower > 12  and next_lower % 12 == 0:
    list1.append(add_one)
if next_higher >= 12 and next_higher % 6 == 0:
    list2.append(add_one)
if next_higher > 12 and next_higher % 9 == 0:
    list2.append(add_one)
if next_higher > 12 and next_higher % 12 == 0:
    list2.append(add_one)

# make a suggestion, but not if the number works 
# in that case, return True
if beads >= 12 and beads % 6 == 0:
    return
if beads >= 12 and beads % 12 == 0:
    return
if beads >= 12 and beads % 9 == 0:
    return

# if number is less than 12, print error message 
if beads < 12:
    print('Please use 12 or more beads in your design.')
    return  

# if number doesn't work, suggest better options     
if len(list1) == len(list2):
    print('\nThere was an error.') 
    print('Try either ' + str(next_lower) + ' or ' \
    + str(next_higher) + ' beads')
elif len(list1) > len(list2):
    print('\nThere was an error.') 
    print('Try ' + str(next_lower) + ' beads instead.')
else:
    print('\nThere was an error.') 
    print('Try ' + str(next_higher) + ' beads instead.')

1 个回答

1

我看过你的代码,并对它做了一些修改。

这些修改的原因我已经在代码里用注释写出来了。

# Test a number for being >= 12 and divisible by 6
test_div_06 = lambda num: num >= 12 and num %  6 == 0

# Test a number for being >= 12 and divisible by 9
test_div_09 = lambda num: num >= 12 and num %  9 == 0

# Test a number for being >= 12 and divisible by 12
test_div_12 = lambda num: num >= 12 and num % 12 == 0

# These are tests in a list
tests = [test_div_06, test_div_09, test_div_12]

# The original if statements were repeated everywhere.
# Now they are defined as functions only once.

def passes_test(test_count):
    # Return a list of the tests applied to a number
    return [test(test_count) for test in tests]

def passes_any(test_count):
    # Return True if any of the tests are True
    return any(passes_test(test_count))

def number_suggestion(bead_count):
    '''
    if number entered does not work, then find the closest 
    usable numbers, figure out which number provides the greatest 
    number of design options and suggest that number. 
    '''
    # Sanity checks should occur first.
    # Why calculate anything if you don't need to?
    # If number is less than 12, print error message 
    if bead_count < 12:
        print("Please use 12 or more beads in your design.")
        return  
    # Number is fine; no suggestion needed
    elif passes_any(bead_count):
        return

    # Find next usable next_lower bead number
    next_lower = bead_count
    while next_lower > 12 and not passes_any(next_lower):
        next_lower -= 1
    low_count = len(passes_test(next_lower))

    # Find next usable next_higher bead number
    next_higher = bead_count
    while next_higher > 12 and not passes_any(next_higher):
        next_higher += 1
    high_count = len(passes_test(next_higher))

    # If number doesn't work, suggest better options     
    # If common behaviour occurs independent of input state,
    # it should be expressed that way.
    # That's why this print statement was moved to here,
    # because the value of counts had no effect on its occurrence.
    print("\nThere was an error.") 
    if low_count == high_count:
        print("Try either %d or %d beads" % (next_lower, next_higher))
    else:
        # The elif and else have been merged into one.
        # The reason being its that their outcome is almost identical.
        # We can calculate the next_best suggestion using an
        # inline if else statement
        next_best = next_lower if low_count > high_count else next_higher
        print("Try %d beads instead." % next_best)

if __name__ == "__main__":
    beads = raw_input("Please specify number of beads: ")
    number_suggestion(int(beads))

撰写回答