自动简化/重构Python代码(如:for循环转列表推导)?

6 投票
1 回答
3551 浏览
提问于 2025-04-17 13:37

在Python中,我特别喜欢用列表推导式来写代码,因为这样可以让实现变得非常简洁。我喜欢用这种方式来写简洁的列表推导式:

myList = [1, 5, 11, 20, 30, 35] #input data
bigNumbers = [x for x in myList if x > 10]

不过,我经常会遇到一些比较冗长的实现,比如这样:

myList = [1, 5, 11, 20, 30, 35] #input data
bigNumbers = []
for i in xrange(0, len(myList)):
    if myList[i] > 10:
        bigNumbers.append(myList[i])

当一个for循环只是在一个数据结构(比如myList[])中查找时,通常可以用一个简单的列表推导式来替代这个循环。
考虑到这一点,有没有什么工具可以把冗长的Python循环转换成简洁的列表推导式呢?


之前的 StackOverflow 问题讨论过如何将循环转换为列表推导式。但我还没有找到关于自动将循环转换为列表推导式的相关问题。


动机:关于“代码干净意味着什么”这个问题,有很多种回答方式。就我个人而言,我觉得让代码简洁、去掉一些多余的部分,通常会让代码更干净、更易读。当然,“简洁的代码”和“难以理解的一行代码”之间是有界限的。不过,我还是觉得写简洁的代码很有成就感,也很舒服。

1 个回答

5

2to3 是一个重构工具,它可以根据你指定的语法模式进行各种重构。你可能想要查找的模式是这个:

VARIABLE1 = []
for VARIABLE2 in EXPRESSION1:
    if EXPRESSION2:
        VARIABLE1.append(EXPRESSION3)

这可以安全地重构为:

VARIABLE1 = [EXPRESSION3 for VARIABLE2 in EXPRESSION1 if EXPRESSION2]

在你的具体例子中,这样做会得到:

bigNumbers = [myList[i] for i in xrange(0, len(myList)) if myList[i] > 10]

然后,你可以进行另一个重构,把 xrange(0, N) 替换为 xrange(N),还有一个重构是把:

[VARIABLE1[VARIABLE2] for VARIABLE2 in xrange(len(VARIABLE1)) if EXPRESSION1]

替换为:

[VARIABLE3 for VARIABLE3 in VARIABLE1 if EXPRESSION1PRIME]

这个重构有几个问题:

  • EXPRESSION1PRIME 必须是 EXPRESSION1,并且所有出现的 VARIABLE1[VARIABLE2] 都要替换成 VARIABLE3。这可以通过 2to3 实现,但需要写一些代码来进行遍历和替换。
  • EXPRESSION1PRIME 中不能再包含 VARIABLE1 的其他出现。这也可以通过写代码来检查。
  • 你需要给 VARIABLE3 起个名字。你选择了 x;但没有合理的方法可以自动完成这个。你可以选择重新使用 VARIABLE1(也就是 i),但这样可能会让人困惑,因为这会让人觉得 i 仍然是一个索引。选择一个合成的名字,比如 VARIABLE1_VARIABLE2(也就是 myList_i),并检查这个名字是否没有被其他地方使用,可能会更好。
  • 你需要确保 VARIABLE1[VARIABLE2] 的结果和使用 iter(VARIABLE1) 时得到的结果是一样的。这一点是无法自动完成的。

如果你想学习如何编写 2to3 的修复器,可以看看 Lennart Regebro 的书。

撰写回答