五大代码异味:你需要提高警惕了!
云栖号资讯:【点击查看更多行业资讯】
在这里您可以找到不同行业的第一手的上云资讯,还在等什么,快来!
作为广泛应用的警告标志,与字面意思不同,代码异味并不是指代码中需要立即注意的漏洞。相反,它反映出代码中更深层次的问题,更确切地说是代码中的裂缝,如果不加以纠正,这些问题可能会在未来导致更严重的后果。
代码异味是弱点或设计缺陷的标志,可能会在可读性、可维护性和可拓展性上导致问题,通常是由不当做法和未使用正确的工具导致的。
Python是最流行的语言之一,这在很大程度上与其相当容易的学习曲线和高度伪英语句法有关,而这却容易令人陷入单一的做事方法。本文中,我们将了解一些典型的Python代码异味案例以及如何避免它们。
可变默认参数
在Python中,使用默认参数是一个很常见的操作,你可以设置一个预定值,并在调用时选择更改。这在设置文字、数字或布尔值时很有用,因为有助于避免出现较长的有冗余值的参数列表。
但是将可变的值设置为默认参数可能是危险的,并且会导致bug。来看以下示例:
def addElements(a=[]): a.append(5) return aaddElements() # [5] addElements() # [5, 5]
相同的函数在每次调用时给出不同的结果。Python中可变默认值的问题是它们只在定义函数时计算一次。每次调用函数时,使用变异值,可能会导致意外的问题,因为跟踪函数调用真的很麻烦。
因此,使用None作为默认值,并在函数中分配可变变量是更安全的,因为你不会以可维护性问题结束,只有在确定需要时才使用可变的默认参数。
选择 range
而不是enumerate
Python的for循环不是最常用的代码编写方式,但有时也会需要到。现在,Python中的for 循环的运行与其他语言不同,你可能会本能地以非惯用的方式编写传统风格的range(len()),如下所示:
names =["a", "b", "c"]for i in range(len(names)): print(i, names[i])
重复基于C-style索引的循环是相当常见的,但这是一种不当做法。其迫使你通过显式索引变量访问元素,所以它不仅Python特性不明显,而且还存在可读性问题。
使用enumerator能提供一个元组的优势,该元组负责同时跟踪索引值和元素。除了更简便,优化程度还更高,它还提供了可选的第二个参数来设置数值。
for i, name in enumerate(names): print(i, name)
忽略内置函数和过度循环
循环不是不能用,但在其中应用转换操作时,它可能会导致冗长的条件代码。在这种情况下,不要忽略已经可以使用的内置函数,如map()filter()和reduce(),这是非常重要的。更重要的是,Python提供了列表解析,这显然是最具Python特性的替换循环方法。
嵌套for循环是代码异味的另一个典型例子。Python程序员在进行模式匹配或一起运行多个迭代时很容易中枪。下列代码一旦再加几行就会看起来不美观:
for x in listA: for y in listB: r.append((x, y))
使用itertools不仅可以提高性能,还更简洁明了。看看上面的代码在itertools.product()中有多整洁:
for x, y in itertools.product(listA,listB): r.append((x, y))
通过使用上面的product,也可以很容易地将其传递到其他高阶函数中。同时在多个列表上同时迭代时,使用zip()函数也不错(如需索引,还可以使用enumerator)。
滥用列表解析
列表解析能灵活创建列表,功能强大,但很容易被误用或滥用,来看一些案例。
- 在不需要时过度进行列表解析
通常,我们开始沉迷于使用列表解析是为了尝试花哨的东西,而不是真需要它。比如在简单的情况下可以使用列表构造函数:
names =["A","B","C"][x.lower() for x in names]#use this list(map(str.lower, names))
- 在实际不存储时使用列表解析
列表解析有助于轻松定义和创建列表,但它们始终存储于内存中。如果不使用系统进程,将有可能损害大数量的数据。因此,使用生成器表达式是更好的选择,因为它按需一次加载一个值。
嵌套分析也需要关注,因为这可能导致可读性问题,知道什么时候使用它,什么时候回退到for循环上是很重要的。
喜欢布尔标志参数和全局变量
布尔是最容易学习的数据类型。在Python中,提供命名参数使工作轻松得多。但是,它们很容易产生嵌套if else块的复杂代码并导致可读性问题。多个布尔存在隐藏的依赖关系,会产生一些问题。因而最好使用枚举,而不是多布尔逻辑。Enum数据类型是可扩展的,可以确保更好的代码结构。
全局变量在所有语言中都是麻烦的,Python也是如此。虽然有时我们确实需要使用它们,但将其误用作传递或访问数据的快捷方式可能很危险,因为它可变。
跟踪它的状态会很棘手,因为你永远不知道谁可能会改变它。如果开始到处使用全局变量,命名冲突则会导致命名空间受到不好的影响。
我们都见过代码异味,神秘的注释、多余的字符串文字和神奇的数字也算代码异味。在编写注释时,重要的是要说明“为什么”部分,因为“什么”部分应该从代码本身得到解释。
你得学会快速定位到代码异味并将其去除。
【云栖号在线课堂】每天都有产品技术专家分享!
课程地址:https://yqh.aliyun.com/live立即加入社群,与专家面对面,及时了解课程最新动态!
【云栖号在线课堂 社群】https://c.tb.cn/F3.Z8gvnK

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
什么是技术情怀
云栖号资讯:【点击查看更多行业资讯】在这里您可以找到不同行业的第一手的上云资讯,还在等什么,快来! 阿里妹导读:什么是技术情怀?在孤尽看来,技术情怀就是:热爱、思考、卓越。正是这种情怀,推动着Java文化的进步。清幽现云山,虚静出内功,《Java开发手册(嵩山版)》今天发布,来听孤尽老师讲他的技术情怀,来看嵩山版又更新了哪些新内容吧。 都说编程是一门艺术,优秀工程师写的代码往往赏心悦目,好代码源于好情怀,好东西自然需要分享出来。回想阿里内部曾组织过一个很有情怀的大型代码分享活动——“向代码致敬,寻找你的第83行代码”,对外以《码出高效》的稿费成立的第83行计划,旨在帮助盲人工程师和山区优秀学生。今天是8月3日,也是《Java开发手册(嵩山版)》发布的日子,在这个数字高度匹配的日子里,我们开怀畅聊一下技术情怀。 工程师是什么样的人? 工程师是一个特殊的群体,在阿里巴巴的占比越来越高,预估即将超过50%,在未来的企业竞争格局中,技术发挥着越来越重要的作用,向技术要红利,向技术要未来。个人以为在技术拓展商业边界之外,需要额外加一条:技术拓展价值边界。这个价值边界的内延是指技术的进无止境,让工...
- 下一篇
JVM系列之:JIT中的Virtual Call
简介 什么是Virtual Call?Virtual Call在java中的实现是怎么样的?Virtual Call在JIT中有没有优化? 所有的答案看完这篇文章就明白了。 Virtual Call和它的本质 有用过PrintAssembly的朋友,可能会在反编译的汇编代码中发现有些方法调用的说明是invokevirtual,实际上这个invokevirtual就是Virtual Call。 Virtual Call是什么呢? 面向对象的编程语言基本上都支持方法的重写,我们考虑下面的情况: private static class CustObj { public void methodCall() { if(System.currentTimeMillis()== 0){ System.out.println("CustObj is very good!"); } } } private static class CustObj2 extends CustObj { public final void methodCall() { if(System.currentTimeMilli...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- CentOS7设置SWAP分区,小内存服务器的救世主
- Mario游戏-低调大师作品
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- 2048小游戏-低调大师作品
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装
- MySQL8.0.19开启GTID主从同步CentOS8
- CentOS8安装Docker,最新的服务器搭配容器使用
- CentOS8安装MyCat,轻松搞定数据库的读写分离、垂直分库、水平分库
- CentOS7编译安装Cmake3.16.3,解决mysql等软件编译问题
- CentOS7,CentOS8安装Elasticsearch6.8.6