python通用规范-7

文章目录

7.1 `List`容量初始化
7.2 元素个数确定时推荐使用Tuple
7.3 推荐使用局部变量引用频繁使用的外界对象
7.4 尽量使用`generator comprehension`代替`listcomprehension`
7.5 使用字符串格式化方式代替"+"和"+="操作符
7.1 List容量初始化

在list成员个数可以预知的情况下,创建list时需预留空间正好容纳所有成员的空间

说明:与Java、C++等语言的list一样,Python语言的list在append()成员时,如果没有多余的空间容纳新的成员,就会分配一块更大的内存,并将原来内存里的成员拷贝到新的内存上,并将最新append()的成员也拷贝到此新内存空间中,然后释放老的内存空间。如果append()调用次数很大,则如上过程会频繁发生,因而会造成灾难性性能下降,而不仅仅是一点下降。
# 错误示例:
members = []
for i in range(1, 1000000):
members.append(i)
len(members)
# 正确示例:
members = [None] * 1000000
for i in range(1, 1000000):
members[i] = i
len(members)
1
2
3
4
5
6
7
8
9
10
7.2 元素个数确定时推荐使用Tuple

在成员个数及内容皆不变的场景下尽量使用tuple替代list

说明:list是动态array,而tuple是静态array(其成员个数以及内容皆不可变)。因此,list需要更多的内存来跟踪其成员的状态。
此外,对于成员个数小于等于20的tuple,Python会对其进行缓存,即当此tuple不再使用时,Python并不会立即将其占用的内存返还给操作系统,而是保留以备后用。
# 错误示例:
myenum = [1, 2, 3, 4, 5]
# 正确示例:
# 如果恰好被缓存过,则初始化速度会为错误示例中的5倍以上。
myenum = (1, 2, 3, 4, 5)
1
2
3
4
5
7.3 推荐使用局部变量引用频繁使用的外界对象

对于频繁使用的外界对象,尽量使用局部变量来引用之

说明:在Python中对一个函数、变量、模块的调用,是以一种字典树的方式来查找的。Python首先会查找locals()数组,这里保存着所有的局部变量;如果找不到,则会继续查找globals()数组;如果在这里也找不到,则会到buildtin(其实是一个模块)中的locals()数组中查找,或者到其它import进来的模块/类中查找。
# 错误示例:
import math
def afunc():
for x in range(100000):
return math.tan(x)
# 在这个例子中,Python会先到 globals()中的名值对字典中,找到math模块;
# 然后在math模块的 locals() 的字典中查找 tan() 函数;
# 然后在当前函数的 locals() 中查找 x。这里存在着3次查找。
# 当调用次数大时,每次调用多出来的1、2次查找,就会被放大。

# 错误示例:
from math import tan
def afunc():
for x in range(100000):
return tan(x)
# 在这个例子中,Python会先到 globals() 的字典中查找tan()函数(其已经被from math import tan语句加载到了globals()中);
# 然后在当前函数的locals()中查找x。这里存在着2次查找,比前一个例子少了一次查找,但是还不是最优解。

# 正确示例:
import math
def afunc(tan=math.tan):
for x in range(100000):
return tan(x)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
在这个例子中,在函数定义时,有且只有一次查找math模块、然后查找tan函数的操作;之后在循环中对tan()函数的调用,都是在afunc()函数的locals()中进行查找,而对函数的locals()中的查找,Python是有特殊优化措施的,速度是非常快的;当然,还包括对本地变量x的查找(也是在当前函数的locals()中查找)。

7.4 尽量使用generator comprehension代替listcomprehension

说明:list comprehension可以用来代替lambda表达式的map、reduce语法,从已有的list中,生成新的数据。而generator comprehension无需定义一个包含yield语句的函数,就可以生成一个generator。 二者一个生成list,另外一个生成generator,在内存的占用上,相差悬殊;在生成速度上,相差无几。

# 错误示例:
even_cnt = len([x for x in range(10) if x % 2 == 0])
# 正确示例:
even_cnt = sum(1 for x in range(10) if x % 2 == 0)
1
2
3
4
7.5 使用字符串格式化方式代替"+“和”+="操作符

使用format方法、"%“操作符和join方法代替”+“和”+="操作符来完成字符串格式化

说明:即使参数都是字符串,也可以使用format方法或%运算符来格式化字符串。一般性能要求的场景可以使用+或+=运算符,但需要避免使用+和+=运算符在循环中累积字符串。由于字符串是不可变的,因此会产生不必要的临时对象并导致二次而非线性运行时间。
# 推荐做法:
x = '%s, %s!' % (imperative, expletive)
x = '{}, {}!'.format(imperative, expletive)
x = 'name: %s; score: %d' % (name, n)
x = 'name: {}; score: {}'.format(name, n)
items = ['<table>']
for last_name, first_name in employee_list:
items.append('<tr><td>%s, %s</td></tr>' % (last_name, first_name))
items.append('</table>')
employee_table = ''.join(items)

# 不推荐做法:
x = imperative + ', ' + expletive + '!'
x = 'name: ' + name + '; score: ' + str(n)
employee_table = '<table>'
for last_name, first_name in employee_list:
employee_table += '<tr><td>%s, %s</td></tr>' % (last_name, first_name)
employee_table += '</table>'

————————————————
版权声明:本文为CSDN博主「zhao12501」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/zhao12501/article/details/115473191

posted @ 2021-07-11 00:17  physique  阅读(229)  评论(0编辑  收藏  举报