python 程序优化字典(自用)

这篇文章用来做<流畅的python>体验备忘录,也作为日后开发的优化字典实用

  1. 快速的创建一个只有简单的属性的class
    用namedtuple构建的class对内存的消耗跟元组是一样的, 因为字段名都被
    存在对应的class里面.跟普通的对象实例比起来也要小一些,因为python不
    会用 dict 来存放这些实例的属性.
#class名为 name ,属性有 a, b
import collections
Name = collections.namedtuple( 'Name' , ['a' , 'b'])
  1. 静态方法的创建与使用
#静态方法就是一个class中定义的一个不使用内部资源的函数, 
#目的可以不经过实例化直接调用, 其意义则是一个 namespace
  1. abs的使用,其实质上并不是 |abs| , 而是 abs2后进行开平方运算, 对于多维数组, 同下
v1 = vector(3, 4)
print (abs( v1 ))
5.0
  1. 对于class作为函数参数传递的理解
#对于class的本质上是不接受任何形式的被传参调用的,但是他有很多种特殊方法,使其看起来像是可以被作为参数传递进去,例如
# r' '  会隐式调用 __repr__ () 方法
# 字符串拼接符号 +   则会隐式调用  __add__()
#下标访问 string[num]    则会隐式调用 __getiem__()
所以,对于开发者来说,实现一个特殊项功能需要用继承或者修改原型进行深度自定义, 
但不了解的情况下, 最好不要触碰触碰这些特殊方法, 否则会导致莫名其妙的bug
  1. 关于len()的独特性理解
#与其他方法不同, vector , array , list 等容器内往往都有一些特殊的内置属性, 
有可能是私有属性, 如 self._len ,他就统计了容器长度, 所以len( array ) 并不需要计算, 
而是直接通过方法来读取私有属性, 这样便走了捷径.
  1. 内置序列的的理解
#容器序列: list , tuple , collections.deque 等
#扁平序列: str , bytes , bytearray , memoryview , array.array
#容器序列是它们所包含的任意类型的对象的引用,而扁平序列则存放的是值而不是引用,
用栈堆来解释看, 扁平序列运行会更加效率,扁平序列只能包含原子数据类型.
  1. 列表推导的深入理解,其中坑多,for循环的书写格式直接导致结果的不同和运行效率的差异,跳转详情

  2. 元组的意义

#元组是对数据的记录: 元组中的每个元素都存放了记录中一个字段的数据, 外加这个字段的位置.
#用来组拆包

9.切片的使用误区

#切片的区间是 [a , b), [0, 10 , -2] 的运行则是 倒着往前切
#对对象进行切片的问题, 内部一定要有特殊方法 __getitem__() 和 __setitem__() ,
对于容器class会有默认的方法,而这种默认方法只能对一维队列进行切片, 如果需要对多维队列切片, 
则需要自定义.
  1. 元组 +=的谜题 bug
t = (1, 2 ,[3, 4])
t[2] += [5, 6]
#其运行结果是  TypeError 都是能够想到的, 然而意想不到的是  t已经被修改成为 (1, 2 , [3, 4, 5, 6]),
但是通过调试测试不出来的, 只有通过 dis.dis('t[2] += [5, 6]'), 查看字节码可以找到原因.

如果看不懂字节码,可以借助tutor可视化工具进行查看,工具很强大.

  1. sort 排序的小技巧
在排序中,list.sort() 是就地排序, 而sorted 则是产生一个新list ,这个虽然都是常识 ,但是 list.sort()同样有返回值, 
返回None,可以通过其返回值进行有效避免bug的存在
a = [3, 4, 1, 6]
if not a.sort():
    print('后续程序继续')
    print(a)
  1. 用bisect来管理已排序的序列
    排序很耗时,如果通过append来尾部插入再进行排序的话,无疑是很蠢的行为,
    如果能够计算出插入元素应该在已排序队列的位置,再进行插入, bisect模块就可以做到.

  2. array模块的现实意义,二进制的高效性
    array是一个扁平容器,可以在栈内进行读写,本质上它是一个原生的C风格数组.

from array import  array
from random import random
from time import ctime

print(ctime())
floats = array('d', (random() for i in range(10**8)))
print(floats[-1])
fp = open('floats.bin', 'wb')
floats.tofile(fp)
fp.close()
floats2 = array('d')
fp = open('floats.bin', 'rb')
floats2.fromfile(fp, 10**8)
fp.close()
print(floats2[-1])

print(ctime())

可以通过改用list测验两者差别, 实测结果是 不用io的情况下,两者耗时相近,但是array占用cpu更低,
而list更容易激起cpu全速,我就跑崩过
用array.fromfile从一个二进制文件读取速度是文本文件的60倍,因为后者会使用内置的float方法把
每一行文字转换成浮点数. 另外写入速度快7倍, 需要的存储空间则会小一倍以上.
所以二进制文件是优选.

  1. 内存视图memoryview
    它能够让用户在不复制内容的情况下,操作同一个数组的不同切片,也是为效率而生

  2. 数学运算 Numpy 和 Scipy
    比如线性代数的矩阵翻转, 把一维list转换成多维等科学计算操作,但是pycharm不自带,需要自行下载安装

  3. collections.deque 双向队列(堆)
    虽然list的 .append 和 .pop(0)合起来用也可以模拟堆,但是从头插入或删除是非常耗时的,
    deque模拟了堆, 可以从头 尾添加,旋转等操作, 但是为了实现这些方法, 付出了一定的代价,
    从队列中间删除元素的操作慢一些,因为它只对在头尾的操作进行了优化

from collections import deque
dq = deque(range(10), maxlen=10)
print(dq)
dq.rotate(3)
print(dq)
dq.rotate(-4)
print(dq)
dq.appendleft(-1)
print(dq)
dq.extend([11, 22, 33])
print(dq)
dq.extendleft([44, 55, 66])
print(dq)
deque([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], maxlen=10)
deque([7, 8, 9, 0, 1, 2, 3, 4, 5, 6], maxlen=10)
deque([1, 2, 3, 4, 5, 6, 7, 8, 9, 0], maxlen=10)
deque([-1, 1, 2, 3, 4, 5, 6, 7, 8, 9], maxlen=10)
deque([3, 4, 5, 6, 7, 8, 9, 11, 22, 33], maxlen=10)
deque([66, 55, 44, 3, 4, 5, 6, 7, 8, 9], maxlen=10)

17.排序中的算法效率问题
list.sort , sorter , max , min 函数的key参数, cmp(a, b)的比较参数之间的区别:
key参数可以对容器中每个元素进行求值,再按照这些值的大小进行排序,后者发生在C语言层
cmp(a, b)则发生在python层,所以不仅仅key可以对不同数据类型的容器元素进行排序,
而且在效率上更快.

未完成,施工中…

猜你喜欢

转载自blog.csdn.net/weilin_8612/article/details/85357416
今日推荐