如何简化重复的函数

3

有没有什么方法可以简化这个函数?我发现其中很多内容都很重复,但是很难想到一种更pythonic或更清晰的方式。相对而言,我对Python比较新,所以希望能得到任何建议。

def colorize(n):
    if n in range(0, 10):
        return selection[-1]
    elif n in range(10, 20):
        return selection[-2]
    elif n in range(20, 30):
        return selection[-3]
    elif n in range(30, 40):
        return selection[-4]
    elif n in range(40, 50):
        return selection[-5]
    elif n in range(50, 60):
        return selection[-6]
    elif n in range(60, 70):
        return selection[-7]
    elif n in range(70, 80):
        return selection[-8]
    elif n in range(80, 90):
        return selection[-9]
    elif n in range(90, 100):
        return selection[-10]
    else:
        return None
5个回答

4
当你遇到大量重复的代码,难以看清如何消除重复时,一个好的技巧是逐渐修改这些代码片段,使它们慢慢相似。如果你做得对,你可以让它们完全匹配。
这种技巧可能看起来很冗长,但好处是它不需要任何大的洞察力。你可以通过小而增量的变化来达成目标,而不必盯着你的代码并“认真思考”。
让我给你展示一下我的意思。
步骤1:将所有的elif转换为直接的if,并删除else。这使它们更加相似,你应该看到它不会改变代码的行为。
if n in range(0, 10):
    return selection[-1]
if n in range(10, 20):
    return selection[-2]
if n in range(20, 30):
    return selection[-3]
if n in range(30, 40):
    return selection[-4]
if n in range(40, 50):
    return selection[-5]
if n in range(50, 60):
    return selection[-6]
if n in range(60, 70):
    return selection[-7]
if n in range(70, 80):
    return selection[-8]
if n in range(80, 90):
    return selection[-9]
if n in range(90, 100):
    return selection[-10]

return None

步骤二:根据一些常见的值计算数字。我们想要提取一个新变量i,使得每个案例都与其他相同。如果我们将i设置为1、2、3等,则可以做到这一点。

让我们考虑第一个案例:

if n in range(0, 10):
    return selection[-1]
如果 i 等于 1,则 10 等于 i*10-1 等于 -i,0 等于 (i-1)*10
i = 1
if n in range((i-1)*10, i*10):
    return selection[-i]

我们可以对第二种情况做同样的事情。
if n in range(10, 20):
    return selection[-2]
同样的公式适用。我们只需要将i更改为2!
i = 2
if n in range((i-1)*10, i*10):
    return selection[-i]

反复洗涤10次,我们得到了这个美丽的结果:
i = 1
if n in range((i-1)*10, i*10):
    return selection[-i]
i = 2
if n in range((i-1)*10, i*10):
    return selection[-i]
i = 3
if n in range((i-1)*10, i*10):
    return selection[-i]
i = 4
if n in range((i-1)*10, i*10):
    return selection[-i]
i = 5
if n in range((i-1)*10, i*10):
    return selection[-i]
i = 6
if n in range((i-1)*10, i*10):
    return selection[-i]
i = 7
if n in range((i-1)*10, i*10):
    return selection[-i]
i = 8
if n in range((i-1)*10, i*10):
    return selection[-i]
i = 9
if n in range((i-1)*10, i*10):
    return selection[-i]
i = 10
if n in range((i-1)*10, i*10):
    return selection[-i]

return None

第三步:现在我们有了10个完全相同的if语句,应该清楚如何将整个过程转换为循环。从i=1循环到i=10即可。

for i in range(1, 11):
    if n in range((i-1)*10, i*10):
        return selection[-i]

return None

好了!所有重复的东西都不见了。


步骤4:如果您想更进一步,可以尝试计算与n相对应的i值,而不是采用上面的猜测和检查方法。我会把这留给您(或其他答案)作为练习。这是一个不错的优化,但它与我刚刚提出的重构类型不同。


3
要在范围0到10内得到1,在范围10到20内得到2,您可以使用Python 3的向下取整整数除法。
x = n // 10 + 1

你可以对此进行取反并将其用于索引。
def colorize(n):
    if 0 <= n < 100:
        return selection[-(n // 10 + 1)]

如果你没有从一个函数中返回任何内容,它会返回None,你不需要明确地返回它。


我认为 if 0 <= n <= 100: 更加合适。 - Marat
@Marat 你是对的,那更合适一些。尽管在原问题中如果 n 是100,那么将返回 None - Iain Shelvington

0
简化重复函数的明显方法是使用循环:
def colorize(n):
    for i in range(0,10):
        if n in range(i*10, (i+1)*10):
            return selection[-i+1]
    return None

我相信有更好的方法来简化你特定的任务,但当你看到这种重复的代码时,循环是一个你应该记在心中的通用模式。


0

试试这个:

def colorize(n):
    for i in range(0,11):
        if n in range((i*10),(i*10)+10):
            return selection[-(i+1)]

0
你可以尝试像这样做:
def colorize(n):
    if n in range(0,100):
        return selection[-1*(n//10+1)]

1
In Python 3 it's O(1). - John Kugelman

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接