不懂性能优化,再强的计算机也白玩

作者阿里云代理 文章分类 分类:linux图文教程 阅读次数 已被围观 744

部分变量更好

记住刚开端学习 C 言语时,对先界说再运用,感到很苦楚,常常由于声明问题编译不通

现在用 Python,变量随用随界说,爽到不可

不过我却养成了先界说在运用的习气,例如:

a = None  # 能够不写 if some_condition:  a = 10 else:  a = 0

尽管a = None能够不写,可是还是习气性的写处理做变量声明,相似 C 中的int a;

这样的习气,促使我在写代码之前,会先考虑如何将会用到的变量,从而,对变量的运用范围做出了严厉的限定,能是部分的,绝不大局

而这个习气提高程序的功用一起,还有其他优点

  • 部分变量查找的速度更快,由于 Python 是从代码块里,向外查找变量的,里面找不到,才会去外面找,终究才是大局变量,其他言语也相同
  • 部分变量更节省内存,当代码块被履行,代码块中声明的部分变量所占用的内存就会被释放
  • 让代码更简练,更易懂,比方能够用部分变量为冗长的命名空间中的变量起别名,如ls = os.linesp,后面就在能够用ls简练表明os.linesp了

函数虽好 尽量少调

函数是个巨大的发明,将能够被重复运用的进程会集起来,方便反复调用,并且函数的呈现,使递归得以实现

不过,调用函数的时间成本比一般语句高的多,这是由于,函数的调用需求计算机做更多的调度和谐作业

因而,应该尽量削减调用函数,特别是在大的循环中,更要留意

下面,列出几个典型比如,在这些情况下,能够不必调用函数

  • 运用isinstance代替type,由于 Python 是面向目标言语,支撑目标的继承,isinstance能够直接检测目标的基类,不会像type相同对目标做全面的检测,会比isinstance做更多的函数调用
  • 防止在循环判断中,调用函数
# 每次循环都需求计算 a 的长度 while i < len(a):  statement # 先计算出 a 的程度,防止每次循环计算 length = len(a) while i < length:  statement
  • 假如模块 X 中有个 Y 目标或函数,那么终究这样引进from X import Y,而不是import X,后者每次运用 Y 时,需求经过X.Y的方法,比直接运用Y多了一次函数调用

映射优于判断

在《编程珠玑 第二版》 第一章开篇中,描绘了一个需求,需求对记录了一千多万行 7 位数据的文件中的数据排序,并且需求在很短时间内,在只运用 1M 内存的条件下完结

关于运用着现代计算机的咱们来说,简直难以想象

一方面,现在的计算机动辄好几 G,几核,功用超强

另一方面,随意一个编程言语都有内置的高效排序算法

但在其时,计算机最大内存才不过几兆(M)!

你可能不会相信,就在其时的条件下,能在数十秒内完结吧

中心原理便是借用索引,来表明数值,比方 1000 是否存在,就看数组中索引为 1000 的值是否为 1,不存在则为 0,终究只需求遍历一遍数组(书上实践应该的是字符串,一个字节索引表明一个数字),就能得到数据排序了

清楚明了,比较判断,索引功率更高

例如,应该尽量防止第一种写法,而用第二种:

# 判断并赋值 if a == 1:  b = 10 elif a == 2:  b = 20 ... # 运用索引,直接存值,功用更好 d = {1:10,2:20,...} b = d[a]

迭代器的功用更优

Python 中有许多迭代器,方便咱们做各种循环

关于能够支撑迭代器的目标,运用迭代器获取元素,比用索引获取元素的功率更高

例如:

a = [1, 2, 3] for i in range(len(a)):  # 运用索引获取元素  print(a[i]) for item in a:  # 运用迭代器获取元素  print(item)

上面代码中,直接运用迭代器的功率更高

假如最开端接触的言语是 Python,应该比较习气直接运用迭代器,假如从其他言语转过来,可能更习气运用索引

另外,假如需求在循环中得到每个元素的索引,能够经过一个索引计数器来实现:

a = ['a', 'b', 'c'] index = 0  # 初始化索引 for item in a:  print(index, item)  index += 1  # 递增索引值

推迟享用是美德

曾经有个著名的心理学试验 —— 棉花糖试验,测验一群小孩子的推迟满意能力,终究的结论是:推迟满意能力强的孩子,未来成功的机率更高

这尽管是对人的测验,但对计算机也适用,不过,背后的逻辑有些不同

对计算机而言,没必要将还用不到的内容加载到内存里,内存就比如咱们的作业太,假如放了太的的东西,查找就比较困难,从而影响作业功率

Python 中供给多种推迟加载的功用,其间生成器是个典型的应用

以list容器为例,在运用该容器迭代一组数据时,必须事先将一切数据存储到容器中,才干开端迭代

而生成器却不同,它能够实现在迭代的一起生成元素,也便是不是一次性生成一切元素,只要在运用时才会生成

下面是个数字生成器的比如

def initNum():  for i in range(10):  yield i gen = initNum()  # 得到生成器 for item in gen: # 遍历生成器  print(item)

调用initNum会返回一个生成器,在for循环中,或许调用next(等同于gen.__next__()) 时才会生成下一个数字,在调用之前,不会生成一切的数据

生成器占用的资源更少,意味着功率更高

先编译再调用

网络上有许多描绘产品经理和研制直接对立的段子,让人啼笑皆非

最主要的原因是,需求的不确定性和研制需求确实定性是彼此对立的

面临不到变动的需求,研制需求不断调整,因而功率不会高

相同的道理,计算机履行已经编译好的程序,比履行边解析边履行的程序功率高许多

例如,C 的程序运转功率会更高,由于需求对 C 代码,编译后才干运转

咱们在享用 Python 这类动态言语带来的便当性一起,尽量让程序履行已经编译好的代码,以便提高功用

例如:

code = "for i in range(3):\n\tprint(i)" exec(code)  # 直接履行 c = compile(code, "", "exec") exec(c)  # 编译后再履行

更常见的是正则表达式

line = "name\t\tage\tschool" reObj = re.compile("\t+")  # 编译 reObj.split(line)  # 运用编译后的功用更好

编译后不只功用更好,并且在能够反复运用时,进一步供给功率

模块化

咱们人类在不断了解这个世界的一起,产生了大量的信息和常识,一向不管哪个人,究其终身也无法把握一切的常识

于是科学发展为分科之学,将常识分门别类,以便不同的人把握了解他所重视的一点

常识是这样,咱们的协作也是如此,没有一个能够做一切的事情,需求多人彼此配合,各负其责

计算机是咱们大脑的延伸,是用咱们的考虑方法、思维习气制造的

面临大规模代码时,需求对代码进行分门别类,不只方便咱们人类检查,还能提高程序履行功率,能够在需求时,才去加载和履行模块和方法

例如:

# module1.py def fun(alist):  for item in alist:  do some thing # 测验用 a = [1, 2, 3] fun(a)

界说了函数fun,之后测验了下,假如其他代码引用了fun:from module1 import fun

这测验用的代码就会被履行

好的方法是,将测验用代码封装起来:

# module1.py def fun(alist):  for item in alist:  do some thing if __name__ == "__main__":  # 测验用  a = [1, 2, 3]  fun(a)

这样就能够防止测验用代码的无意义履行,从而提高运转功率

总结

尽管现在的计算机功用很强,编程言语提高的功用许多,为咱们提高了极大的便当,可是良好的编程习气和编码标准仍然是很重要的,首要代码更多的时候是写给人看的,另外再强的计算机功用,也解决不了思维懒散者的低效代码,就比如 你永远叫不醒一个装睡的人 相同。

业精于勤,在日常的作业和编程中,多学多练多考虑,会使编程水平的提高事半功倍,看似不起眼的小技巧,处处做好了,将带来巨大的差异,这便是与高手直接的距离

期望今天共享的一点小技巧能给您一丝启示,让您在通往高手的道路上愈加顺畅,比心!

本公司销售:阿里云、腾讯云、百度云、天翼云、金山大米云、金山企业云盘!可签订合同,开具发票。

我有话说: