Python异味总结
1.严重
1.1 功能的认知复杂性不应过高
认知复杂性是衡量一个功能的控制流程有多难理解的标准。 具有高度认知复杂性的功能将很难维持。
for i in range(100): # +1
...
if ...: # +2
....
else: # +2
....
for i in range(100): # +3
if ...: # +4
...
else: # +4
....
# 认知复杂度高于15视为严重异味,此代码为16
2.主要
2.1 应合并可折叠的“if”语句
合并可折叠的if语句可以提高代码的可读性。
- Noncompliant Code Example
if condition1:
if condition2:
# ...
- Compliant Solution
if condition1 and condition2:
# ...
2.2 函数名称应符合命名约定
共享编码约定允许团队高效协作。此规则检查所有函数名是否与提供的正则表达式匹配。
- Noncompliant Code Example
- With the default provided regular expression: 1[a-z0-9_]{2,30}$
def MyFunction(a,b):
...
- Compliant Solution
def my_function(a,b):
...
2.3 函数、方法和lambda不应有太多的参数
一个长的参数列表可能表示应该创建一个新的结构来封装大量的参数,或者表示函数正在做太多的事情。
- Noncompliant Code Example
- With a maximum number of 4 parameters:
def do_something(param1, param2, param3, param4, param5):
...
- Compliant Solution
def do_something(param1, param2, param3, param4):
...
2.4 嵌套的代码块不应为空
大多数情况下,当确实缺少一段代码时,代码块是空的。因此,必须填充或移除此类空块。
- Noncompliant Code Example
for i in range(3):
pass
- Exceptions
- When a block contains a comment, this block is not considered to be empty.
2.5 应删除多余的括号对
使用括号,即使是那些不需要强制执行所需操作顺序的括号,也可以澄清代码背后的意图。但多余的括号对可能会产生误导,应该删除。
- Noncompliant Code Example
return ((3)) # Noncompliant
return ((x + 1)) # Noncompliant
x = ((y / 2)) + 1 # Noncompliant
- Compliant Solution
return 3
return (3)
return x + 1
return (x + 1)
x = y / 2 + 1
x = (y / 2) + 1
2.6 代码部分不应注释掉
程序员不应该注释掉代码,因为它会使程序膨胀并降低可读性。
应该删除未使用的代码,如果需要,可以从源代码管理历史记录中检索。
- See
- MISRA C:2004, 2.4 - Sections of code should not be “commented out”.
- MISRA C++:2008, 2-7-2 - Sections of code shall not be “commented out” using C-style comments.
- MISRA C++:2008, 2-7-3 - Sections of code should not be “commented out” using C++ comments.
- MISRA C:2012, Dir. 4.4 - Sections of code should not be “commented out”
2.7 不应使用“print语句
在Python 3.0中删除了print语句。应改用内置函数。
- Noncompliant Code Example
print '1' # Noncompliant
- Compliant Solution
print('1')
2.8 条件结构中的两个分支不应具有完全相同的实现
在相同的if结构中有两个分支,并且实现相同,充其量是重复的代码,最坏的是编码错误。如果两个实例确实需要相同的逻辑,那么应该将它们结合起来。
- Noncompliant Code Example
if 0 <= a < 10:
do_first()
do_second()
elif 10 <= a < 20:
do_the_other_thing()
elif 20 <= a < 50:
do_first() # Noncompliant; duplicates first condition
do_second()
- Exceptions
- 忽略包含单行代码的if链中的块。
if 0 <= a < 10:
do_first()
elif 10 <= a < 20:
do_the_other_thing()
elif 20 <= a < 50:
do_first() # no issue, usually this is done on purpose to increase the readability
- 但当所有分支都具有相同的单行代码时,此例外情况不适用。
if 0 <= a < 10:
do_first()
elif 20 <= a < 50:
do_first() # Noncompliant, this might have been done on purpose but probably not
3 次要
3.1 不应不必要地使用“pass”
在语法不需要的地方使用pass语句纯粹是粗制滥造,应该删除它。
- Noncompliant Code Example
def __init__(self, log="", who="", date=0, files=[]):
self.log = log
self.files = files
self.who = who
self.date = date
pass # Noncompliant
def lookup():
pass # Compliant; method can't be empty
- Compliant Solution
def __init__(self, log="", who="", date=0, files=[]):
self.log = log
self.files = files
self.who = who
self.date = date
def lookup():
pass
3.2 类名应符合命名约定
共享编码约定允许团队有效协作。此规则允许检查所有类名是否与提供的正则表达式匹配。
- Noncompliant Code Example
- With default provided regular expression 2[a-zA-Z0-9]*$:
class myClass:
...
- Compliant Solution
class MyClass:
...
3.3 字段名称应符合命名约定
共享一些命名约定是使团队能够高效协作的关键。此规则允许检查字段名是否与提供的正则表达式匹配。
- Noncompliant Code Example
- With the default regular expression 3[_a-z0-9]*$
class MyClass:
myField = 1
- Compliant Solution
class MyClass:
my_field = 1
3.4 局部变量和函数参数名称应符合命名约定
共享命名约定允许团队有效协作。当局部变量或函数参数名称与提供的正则表达式不匹配时,此规则会引发问题。
- With the default regular expression 4[_a-z0-9]*$
- Exceptions
- 此规则忽略循环计数器
for i in range(limit): # Compliant
print(i)
3.5 方法名称应符合命名约定
共享一些命名约定是使团队能够高效协作的关键。此规则允许检查所有方法名称是否与提供的正则表达式匹配。
- Noncompliant Code Example
- With default provided regular expression: 5[a-z0-9_]{2,30}$
class MyClass:
def MyMethod(a,b):
...
- Compliant Solution
class MyClass:
def my_method(a,b):
...
3.6 应删除未使用的局部变量
如果局部变量已声明但未使用,则它是死代码,应该删除。这样做将提高可维护性,因为开发人员不会怀疑该变量的用途。
- Noncompliant Code Example
def hello(name):
message = "Hello " + name # Noncompliant
print(name)
for i in range(10):
foo()
- Compliant Solution
def hello(name):
message = "Hello " + name
print(message)
for _ in range(10):
foo()
- Exceptions
- “_” 以及元组不会对此规则提出问题。以下示例符合要求:
for _ in range(10):
do_something()
username, login, password = auth
do_something_else(username, login)