6 个例子教你重构 Python 代码

Python猫

共 2575字,需浏览 6分钟

 ·

2020-11-25 19:53

 △点击上方Python猫”关注 ,回复“1”领取电子书

剧照 | 《棋魂》

编写干净的 Pythonic 代码就是尽可能使其易于理解,但又简洁。所以重构代码让代码简洁易理解是很有必要的。


本文重点是想跟大家探讨为什么这些重构是好想法,而不仅仅是如何做。




1. 合并嵌套的 if 条件


太多的嵌套会使代码难以理解,这在 Python 中尤为如此,因为 Python 没有括号来帮助区隔不同的嵌套级别。


阅读深度嵌套的代码容易让人烦躁,因为你必须理清哪些条件属于哪一级。因此,我们应尽可能减少嵌套,如果两个条件可以用 and 合在一起,会比嵌套更易读。


合并之前:

if a:    if b:        return c

合并后:

if a and b:    return c

2. 将重复的代码移到条件语句之外


我们应该始终寻找移除重复代码的方法。这是提升代码能力的好办法。


有时,在条件的两个分支上出现重复代码,这意味这段代码将始终执行。因此这段重复的代码可以从条件中移出,放在条件之外执行。

if sold > DISCOUNT_AMOUNT:    total = sold * DISCOUNT_PRICE    label = f'Total: {total}'else:    total = sold * PRICE    label = f'Total: {total}'

通过将对label变量赋值移到到条件之外,我们删除了重复的代码行,并明确了条件实际控制的内容,就是计算total。

if sold > DISCOUNT_AMOUNT:    total = sold * DISCOUNT_PRICEelse:    total = sold * PRICElabel = f'Total: {total}'

3. 将内部循环中的yield替换为yield from


经常忽略的一个小窍门是 Python 的yield关键字有对应的为collections准备的yield from。因此无需使用 for 循环遍历集合。这使代码变短,并删除 for 中的额外变量。而且消除 for 循环后,yield from使程序运行效率提高约 15%。


重构前:

def get_content(entry):    for block in entry.get_blocks():        yield block

重构后:

def get_content(entry):    yield from entry.get_blocks()

4. 使用 any() 而不是用于循环


常见的模式是,我们需要查找是否集合中的一个或多个项符合某些条件。这可以通过 for 循环完成,例如:

found = Falsefor thing in things:    if thing == other_thing:        found = True        break

更简洁的方法,是使用 Python 的 any() 和 all()内置函数,来清楚地显示代码的意图。

found = any(thing == other_thing for thing in things)

当至少有一个元素计算为 True 时,any() 将返回 True,只有当所有元素都计算为 True 时,all() 将返回 True。


如果对 any() 的调用找到一个值为 True 的元素,它可以立即返回。


5. 用[]替换list()


创建列表的最简洁和 Pythonic 的方法是使用 []。

x = []x = ['first', 'second']

这样做有额外的优点:是一个很好的改进程序性能的方法。


以下是更改之前和之后的时间对比:

$ python3 -m timeit "x = list()"5000000 loops, best of 5: 63.3 nsec per loop

$ python3 -m timeit "x = []"20000000 loops, best of 5: 15.8 nsec per loop

同样的原因和性能表现,使用{}替代dict()。


6. 将重复执行的语句移出for/while循环


将“不变的”语句从循环中移出。如果某条语句只是设置了一些变量供循环使用,则不需要在循环中。循环本身就是复杂的,因此在编写循环时,应牢记,使其更短、更容易理解。


在此示例中,city变量在循环中赋值,但它只读取且不更改。

for building in buildings:    city = 'London'    addresses.append(building.street_address, city)

因此,将其移出是安全的,这更清楚地说明,相同的city值将应用于每个building变量。

city = 'London'for building in buildings:    addresses.append(building.street_address, city)

这也是提高了程序性能 ,因为如果循环中的任何语句将在每次循环运行时执行。在这些多次执行上花费的时间属于浪费,因为它只需要执行一次。如果语句涉及对数据库的调用或其他耗时的任务,则这种节省可能非常重要。


参考链接:

https://sourcery.ai/blog/explaining-refactorings-1

Python猫技术交流群开放啦!群里既有国内一二线大厂在职员工,也有国内外高校在读学生,既有十多年码龄的编程老鸟,也有中小学刚刚入门的新人,学习氛围良好!想入群的同学,请在公号内回复『交流群』,获取猫哥的微信(谢绝广告党,非诚勿扰!)~

近期热门文章推荐:

非常干货:Python 探针实现原理
Python如何异步发送日志到远程服务器?
Python 为什么能支持任意的真值判断?
Python 项目提速技巧:连接复用

感谢创作者的好文
浏览 11
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报