1,考虑使用contextlib和with语句改写可复用的try/finally代码

  1. with lock:print('lock is held')相当于try:print('lock is held')finally:lock.release,使用with可以避免繁琐的语句
  1. 开发者可以使用内置的contextlib模块的contextmanager修饰器来处理自己编写的对象和函数以支持with语句,这样做比标准写法更便捷,如果使用标准方式写,需要定义新类并提供__enter__和__exit__方法
    from contextlib import contextmanager
    
    #上下文管理器
    @contextmanager
    def test():
    print("初始化")
    #可以在这里开启资源,如log等级上升
    try:
    print("with开始")
    #如果有错误会通过yield弹出
    yield
    finally:
    print("离开时释放资源") with test():
    print("go")
  1. 可以在yield处弹出一个对象,通过as指定为一个局部变量,在with内可以对其进行交互

2,使用copyreg实现可靠的pickle操作

  1. python内置的pickle模块能将python对象转化为字节流,也能把字节反序列化为python对象,但pickle处理后的数据实际上就是一个程序,可能会混入恶意信息,对程序造成损坏,json产生的数据是一种安全的信息,只描述对象如何构成,不会造成额外风险,所以pickle处理的字节流不应该在未受信任的程序之间传播
  1. 例如定义一个GameState类,实例化为对象state=GameState()包含玩家的当前游戏状态,生命,金币等等,玩家退出游戏的时候,将state直接写到一份文件里,游戏加载时读取
    with open(path,'wb') as f:
    pickle.dump(state,f) with open(path,'rb') as f:
    state_after=pickle.load(f)
    print(state_after.__dict__)
  1. 如果类新增加了一些属性,但保存的对象仍然是旧的,那就需要使用copyreg了,先将类添加一个__init__构造器,通过传参的方式初始化属性,然后使用如下代码注册函数,序列化和反序列化仍然按照原来的方式使用即可
    def unpickle_game_state(kwargs):
    return GameState(**kwargs)#返回State实例化 def pickle_game_state(game_state):#参数为State对象
    kwargs=game_state.__dict__#获取其属性 #序列化封装需要返回反序列化的函数和参数
    return unpickle_game_state,(kwargs,) copyreg.pickle(GameState,pickle_game_state)#注册pickle函数
  1. 使用版本号管理类,修改copyreg注册的pickle函数,在里面添加一个版本号的参数kwargs['version]=2,然后在反序列化函数中根据版本号对其进行操作,即可兼容版本
  1. 固定引入路径,若重构时,将类名修改或删除,那么反序列化的时候会出错,使用copyreg.pickle注册后,会自动指向unpickle函数,所以不用担心修改类名的问题,但如果没有使用copyreg注册,那么修改类名后反序列化就会报错

4,使用datetime模块处理本地时间而不是time模块

  1. time模块,内置的time模块中有一个名叫localtime的函数,可以把UNIX时间戳(timestamp即UTC时刻距离UNIX计时原点的秒数)转换为宿主计算机时区的当地时间,这个模块不够稳定,只能转换主机时区的时间,其它地区会出错,应该尽量不用,而是使用datetime模块
    from time import localtime,strftime,strptime,mktime
    time_format='%Y-%m-%d %H:%M:%S'
    time_str=strftime(time_format,localtime(1407694710))
    #将时间戳转换为当地时间
    print(time_str) #将本地时间转化为UTC时间
    #strptime解析时间字符串,mktime将本地时间转换为UNIX时间戳
    print(mktime(strptime(strptime(time_str,time_format))))
  1. datetime模块
    from datetime import datetime,timezone
    from time import mktime #UTC时间转本地时间
    now=datetime(2014,8,10,18,18,30)
    now_utc=now.replace(tzinfo=timezone.utc)
    #注意此处若想可靠的转换时区,还需要搭配pytz模块
    now_local=now_utc.astimezone()#此处只包含UTC时区
    print(now_local) #本地时间转UTC格式时间戳
    time_str='2014-08-10 11:18:30'
    time_format='%Y-%m-%d %H:%M:%S'
    now=datetime.strptime(time_str,time_format)
    time_tuple=now.timetuple()
    utc_now=mktime(time_tuple)
    print(time_tuple)
  1. 若要在不同时区之间执行可靠的转换操作,还需要搭配pytz模块使用

5,内置的数据结构与算法 (开发者不应该自己去重新实现,因为很难把他们写好)

  1. 双向队列,collections模块中的deque类,从该队列头部与尾部插入或移除一个元素,只有O(1)的时间复杂度
    d=deque()
    d.append(1)
    x=d.popleft()
  1. 有序字典,collections模块中的OrderedDict类,它能够按照键的插入顺序,保留键值对在字典中的次序。标准字典是无序的,也就是说,在相同键值对的两个字典上迭代可能出现不同的迭代顺序
    a=OrderedDict()
    a['x']=1
  1. 默认值字典,collections模块中的defaultdict类,本例中用int函数创建字典,默认值为0
    stats=defaultdict()
    stats['my_counter']+=1
  1. 堆队列(优先队列),heapq模块中的heappush、heappop和nsmallest等函数,能够在标准的list中创建堆结构,时间复杂度O(logn),普通列表O(n)
    a=[]
    heappush(a,5)
    heappush(a,3)
    heappush(a,7)
    heappush(a,4)
    #总是能弹出优先级较高的元素,
    #默认是越小元素优先级越高
    print(heappop(a))
    #即使调用sort后依然能保持堆结构
    a.sort()
  1. 二分查找,bisect模块中的bisect_left函数,使用Index查找复杂度为O(n),二分为O(logn),注意:使用前列表应排好序,bisect搜索一百万个元素的列表,与index搜索包含14个元素的列表,所耗时间差不多
    i_index = bisect_left(alist,number)
  1. 与迭代器有关的工具,itertools模块,可分为三大类

♦ 能够把迭代器连接起来的函数:

  • chain:将多个迭代器按顺序连成一个迭代器
  • cycle:无限重复某个迭代器中的各个元素
  • tee:把一个迭代器拆分成多个平行的迭代器
  • zip_longest:与内置的zip函数相似,可以应对不同长度的迭代器

♦ 能够从迭代器中过滤元素的函数:

  • islice:在不复制的前提下,根据索引值来切割迭代器获取迭代器的一部分
  • takewhile:在判定函数为True的时候,从迭代器逐个返回元素
  • dropwhile:从判定函数初次为False的地方开始,逐个返回迭代器中的元素
  • filterfalse:从迭代器中逐个返回能令判定函数为False的所有元素,效果与filter函数相反

♦ 能够把迭代器中的元素组合起来的函数:

  • product:根据迭代器中的元素计算笛卡尔积(就是x*y),并返回。可以使用product改写深度嵌套的列表推导操作
  • permutations:用迭代器中的元素构建长度为N的有序排列,例:permutations('ABCD',2) # AB AC AD BA BC BD CA CB CD DA DB DC
  • combination:用迭代器中的元素构建长度为N的无序组合,例:combinations('ABCD', 2) # AB AC AD BC BD CD

备注:如果发现自己需要编写一段非常麻烦的迭代程序,应该花些时间看看itertools的文档看看有没有现成的工具可以用

6,在重视精度的场合,使用decimal模块中的Decimal类,该类默认提供28个小数位,以进行定点数学运算,有需要可以把精度提的更高

  1. dec=Decimal('1.45')在decimal之间进行计算会得到精确的结果,计算后的类型仍然是Decimal类型,print(dec)
  1. Decimal类提供quantize内置函数,它可以按照精度和舍入方式精确的调整数值result=dec.quantize(Decimal('0.01'),rounding=ROUND_UP)print(result)
  1. 若要使用精度不受限的方式表达有理数,那么可以考虑使用Fraction类,包含在内置的fractions模块里

7,学会使用pypi,Python中央仓库:https://pypi.python.org

  1. 如果碰到不熟悉的编程难题,应该去PyPI里看看别人的代码
  1. pip3安装python3版本的软件包,pip安装python2版本的软件包

最新文章

  1. javascript 导出Excel
  2. 【leetcode】Combination Sum
  3. 20150820 PROCEDURE 模板
  4. git常见指令
  5. 为什么ELF文件的加载地址是0x8048000
  6. android如何使用自己定义JNI接口,以及NDK环境建设和使用的工具。
  7. 【Android Developers Training】 42. 从另一台设备接收文件
  8. VBA小技巧
  9. TeamViewer 服务队列网页怎么打开?有什么用?
  10. 新闻娱乐类APP的后端核心逻辑总结
  11. 被遗弃的depends2.2,替换解决方案——VS命令行
  12. 区分range() , np.arange() , np.linspace()
  13. ubuntu下配置环境
  14. session和cookie的作用和原理
  15. C 语言宏定义
  16. Beta冲刺三——《WAP团队》
  17. Win10/Ubuntu双系统安装常见问题
  18. PHP文件引入
  19. js_面向对象设计和行为委托设计模式
  20. numpy.linspace介绍

热门文章

  1. 修改从Maven中心仓库下载到本地的jar包的默认存储位置及远程仓库
  2. MySQL5.6 数据库主从(Master/Slave)同步安装与配置详解
  3. 你有哪些相见恨晚的Chrome 扩展?
  4. 有点长的博客:Redis不是只有get set那么简单
  5. 利用动态资源分配优化Spark应用资源利用率
  6. Linux永久开放端口
  7. javascript常用工具函数总结(不定期补充)未指定标题的文章
  8. cmd 输入输出
  9. web架构之Nginx简介(1)
  10. 深度学习与人类语言处理-语音识别(part1)