Python——常见注意事项
编写代码的一个有效准则:先让它能用,再让它更快。一旦有了一个能用的程序,就可以专注于提高它的效率了。
选择简单易懂的名称
除非编写的代码是“一次性”的,仅需运行一次,不需要长期维护,否则应该在命名这件事上花些工夫。如果只是简单地用a,b,c作为变量名,将会花费不必要的心里会议当初这些变量的作用。
计算机并不在乎名称是否言简意赅还是语焉不详。名称的作用是让人更容易阅读而不是让计算机更容易运行。
注意事项
- 不要覆盖内置名称
- 标识符区分大小写,且不能包含空格。
- 数据类型的前缀,需要删除
- 不要带有连续数字后缀的名称
- 如果是在大项目中,查找功能会经常使用,所以请包含具体细节的较长且特殊的名称
- 避免笑话、双关语和需要文化背景才能理解的词汇
命名风格
- 蛇形命名法
(snake_case)用下划线分割单词,两个单词之间的连接看起来像是蛇一样。这种情况下,所有字母都是小写,但常量名经常采用大写,类似于 UPPER_SNAKE_CASE
- 驼峰命名法
(camelCase)从第二个单词开始,每个单词使用首写字母大写进行分隔,也就是第一个单词手写字母小写,后面的单词的大写字幕看起来像驼峰。
- Pascal命名法
(PascalCase)因其在Pascal编程语言中的使用而得名。它跟驼峰命名法类似,但第一个单词的首字母也要大写。
适当的名称长度
-
名称太短
1. 只有一个或两个字母的名称对代码的人而言很省事,但对别人而言很难读懂。
2. 缩写名称比如mon,可以用来代表监视器、月份、怪物等单词
3. 单个词语,像是start,不明白是什么的开始。
-
名称太长
1. 呈现过多的细节,描述性过强的名称
PEP8的命名风格
- 所有的字母应是ASCII字母,也就是没有重音符号的大写和小写的英文字母
- 模块名应该简短,都是小写字母
- 类名应使用Pascal命名法
- 常量名应使用大写字母的蛇形命名法
- 函数名、方法名和变量名应使用小写字母的蛇形命名法
- 方法的第一个参数,应总是命名为小写的self
- 类方法的第一个参数应总是命名为小写的cls
- 类中的私有属性应总是以下划线(_)开头
- 类中的公共属性不应以下划线开头
重复代码
应该把去重工作,放在写代码的每一个环节尽量使代码可用性和复用性强。杜绝出现大量的重复代码而影响修改、删除和编辑的工作量。
通过把代码放在一个函数或者循环中,使其在代码中只出现一次。
一般来说,重复代码片段越长,或者在程序中出现的重复次数越多,就越应该删除。并不介意复制粘贴一次甚至两次代码,但一般当代码存在三四个副本时,就应该考虑去重。
魔数
程序包含数字很正常,但代码中出现的一些数字可能会让其他程序员赶到困惑。
expiration = time.time() + 604800
expiration = time.time() + 604800 #一周后过期
上面的这种方式是可以的,但是最好的方式是使用常量来书写。
常量是一类用大写字母书写的量,其数值在初始赋值后不应该改变。通常在源代码文件的顶部来定义作为全局变量的常量
# 设置不同时间量的常量
SECONDS_MINUTE = 60
SECONDS_HOUR = 60 * SECONDS_MINUTE
SECONDS_DAY = 24 * SECONDS_HOUR
SECONDS_WEEK = 7 * SECONDS_DAY
expiration = time.time() + SECONDS_WEEK # 一周后过期
及时数值相同,也应该为有着不通目的的魔数采用不同的常量。这样会有利于将来对他们进行独立的修改。
可以用在非数字值
当字符串拼写错误时,会很难出现bug的。但如果我们使用常量,错误拼写就会导致程序崩溃。
NORTH = 'north'
print(NOTH)
#NameError: name 'NOTH' is not defined. Did you mean: 'NORTH'?
魔数是一种代码的坏味道,因为他们没有表明数字的目的,降低了代码的可读性,使其难以维护,并且容易出现难以察觉的拼写错误。解决方法时使用常量代替魔数
注释的代码和死代码
注释的代码即某一行代码进行了注释,但如果该代码提交给另一个工程师,那么会有疑问,这行注释过的代码是因为什么而被注释的。
最好将这些确定无用和容易被误解的注释代码要不删除,要不进行注解。
test()
# test1()
test2()
test1()
死代码就是指无法到达或逻辑上永远无法运行的代码。
def test(num):
if 1== num:
return 1111
else:
return 0000
return 99999
print(test(22))
其中的return 99999就是一个死代码。因为它永远都无法运行,在else中就会返回。
注释过的代码和死代码会形成误导,让程序员认为这些代码是程序的可执行部分。
如果后期会有可能是需要恢复的代码,可以使用版本控制进行后期的恢复。
注释的重要性
代码的注释与文档的重要性不亚于代码本身,因为软件永远不会彻底完成,你总是需要修改,要么添加心功能,要么修复错误。
test = 8 # 内联注释,多用于变量注释
# 单行注释
test()
"""
多行注释
多行注释
"""
test() # 内敛注释
if test:
# 内联注释
test = 1
代码标签和TODO注释
用于提示程序员有哪些工作要做。以全大写字母标签开头,后面是简短描述的注释。
# TODO: 提示需要完成的工作
# FIXME: 提示这部分代码还不能正常工作
# HACK: 提示这部分代码可以工作,但可能有些勉强,需要做出改进
# XXX: 通常用于提示高度严重的问题
检索模块、类、函数或方法的文档字符串
"""
test111111111
"""
class test(object):
"""
test22222222222
"""
def get(self):
"""
test333333333333
:return:
"""
pass
print(__doc__)
print(test.__doc__)
print(test.get.__doc__)
打印调试
戒掉print,使用print确实快速简单,但每写一段代码就运行一次print,那么会有很多的重复运行程序。
为了戒掉总使用print,或者对自己编写的程序没有一个清晰的认知。可以使用调试器或者日志进行问题的记录。
使用调试器可以逐行运行程序中的代码并检查所有变量,从长远来看,更能节省时间。并且在大的系统中,不可能随意的提取出来某一个代码就运行起进行测试。
日志记录
日志文件可以记录程序的大量信息,能够用来比较一次运行产生的信息和以往运行的信息。在python中,内置的日志模块提供了这一功能。
import logging
logging.basicConfig(filename='system_error.txt',level=logging.DEBUG,
format='%(asctime)s - %(levelname)s - %(message)s')
test=1111111
logging.debug(test)
注意,这里的日志输出不是系统bug的输出,如果系统错误,是需要使用try来处理的。而这里的日志是想要读取某一个字段的内容而设计的。
带有数字后缀的变量
在变量后面最好不要带有一系列的数字,像:password1,password2这种,因为不确定后面还有没有这种带有数字的,并且不明确数字的意义。最好使用passowrd和confirm_password。
本该是函数或者模块的类
就是不要让单一的代码程序复杂化,如果一个类或一个函数所表现的只是一个单一的功能,或者没有那么复杂,或者没有在各种地方被调用。那就让它简单化。不要去覆盖那么多的类或者函数。
巧妙利用推导式
通常形式:
spam = []
for number in range(1,100):
if number % 5 != 0:
spam.append(number)
列表生成式
spam = [number for number in range(1,100) if number % 5 !=0]
print(spam)
集合生成式
spam = {number for number in range(1,100) if number % 5 !=0}
print(spam)
字典生成式
spam = {str(number):number for number in range(1,100) if number % 5 !=0}
print(spam)
多重嵌套
#将嵌套式列表,更改为平铺列表。
testlist = [[0,1,2,3],[4],[5,6,7],[8,9]]
net_list = [addlist for sublist in testlist for addlist in sublist]
print(net_list)
虽然使用多层嵌套可以节省代码量,但是在阅读起来会有一定的复杂度。所以要慎重的进行多重嵌套。