自动简化/重构Python代码(如:for循环转列表推导)?
在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 的书。