• linkedu视频
  • 平面设计
  • 电脑入门
  • 操作系统
  • 办公应用
  • 电脑硬件
  • 动画设计
  • 3D设计
  • 网页设计
  • CAD设计
  • 影音处理
  • 数据库
  • 程序设计
  • 认证考试
  • 信息管理
  • 信息安全
菜单
linkedu.com
  • 网页制作
  • 数据库
  • 程序设计
  • 操作系统
  • CMS教程
  • 游戏攻略
  • 脚本语言
  • 平面设计
  • 软件教程
  • 网络安全
  • 电脑知识
  • 服务器
  • 视频教程
  • vbs
  • DOS/BAT
  • hta/htc
  • python
  • perl
  • VBA
  • ColdFusion
  • ruby
  • PowerShell
  • Lua
  • Golang
  • linux shell
您的位置:首页 > 脚本语言 >python > python编码最佳实践之总结

python编码最佳实践之总结

作者:lijiao 字体:[增加 减小] 来源:互联网

lijiao 通过本文主要向大家介绍了python 编码,python 编码转换,python编码问题,python编码规范,python编码声明等相关知识,希望对您有所帮助,也希望大家支持linkedu.com www.linkedu.com

相信用python的同学不少,本人也一直对python情有独钟,毫无疑问python作为一门解释性动态语言没有那些编译型语言高效,但是python简洁、易读以及可扩展性等特性使得它大受青睐。

 工作中很多同事都在用python,但往往很少有人关注它的性能和惯用法,一般都是现学现用,毕竟python不是我们的主要语言,我们一般只是使用它来做一些系统管理的工作。但是我们为什么不做的更好呢?python zen中有这样一句:There should be one-- and preferably only one --obvious way to do it. Although that way may not be obvious at first unless you're Dutch. 大意就是python鼓励使用一种最优的方法去完成一件事,这也是和ruby等的一个差异。所以一种好的python编写习惯个人认为很重要,本文就重点从性能角度出发对python的一些惯用法做一个简单总结,希望对大家有用~

    提到性能,最容易想到的是降低复杂度,一般可以通过测量代码回路复杂度(cyclomatic complexitly)和Landau符号(大O)来分析, 比如dict查找是O(1),而列表的查找却是O(n),显然数据的存储方式选择会直接影响算法的复杂度。

一、数据结构的选择
1. 在列表中查找:

 对于已经排序的列表考虑用bisect模块来实现查找元素,该模块将使用二分查找实现

def find(seq, el) :
  pos = bisect(seq, el)
  if pos == 0 or ( pos == len(seq) and seq[-1] != el ) :
    return -1
  return pos - 1
</div>

而快速插入一个元素可以用:

 bisect.insort(list, element) 
</div>

这样就插入元素并且不需要再次调用 sort() 来保序,要知道对于长list代价很高.

2. set代替列表:

 比如要对一个list进行去重,最容易想到的实现:

seq = ['a', 'a', 'b']
res = []
for i in seq:
  if i not in res:
    res.append(i)
</div>

显然上面的实现的复杂度是O(n2),若改成:

seq = ['a', 'a', 'b']
res = set(seq)
</div>

复杂度马上降为O(n),当然这里假定set可以满足后续使用。

另外,set的union,intersection,difference等操作要比列表的迭代快的多,因此如果涉及到求列表交集,并集或者差集等问题可以转换为set来进行,平时使用的时候多注意下,特别当列表比较大的时候,性能的影响就更大。

3. 使用python的collections模块替代内建容器类型:

collections有三种类型:

deque:增强功能的类似list类型
defaultdict:类似dict类型
namedtuple:类似tuple类型

       列表是基于数组实现的,而deque是基于双链表的,所以后者在中间or前面插入元素,或者删除元素都会快很多。

       defaultdict为新的键值添加了一个默认的工厂,可以避免编写一个额外的测试来初始化映射条目,比dict.setdefault更高效,引用python文档的一个例子:

#使用profile stats工具进行性能分析

>>> from pbp.scripts.profiler import profile, stats
>>> s = [('yellow', 1), ('blue', 2), ('yellow', 3),
... ('blue', 4), ('red', 1)]
>>> @profile('defaultdict')
... def faster():
... d = defaultdict(list)
... for k, v in s:
... d[k].append(v)
...
>>> @profile('dict')
... def slower():
... d = {}
... for k, v in s:
... d.setdefault(k, []).append(v)
...
>>> slower(); faster()
Optimization: Solutions
[ 306 ]
>>> stats['dict']
{'stones': 16.587882671716077, 'memory': 396,
'time': 0.35166311264038086}
>>> stats['defaultdict']
{'stones': 6.5733464259021686, 'memory': 552,
'time': 0.13935494422912598}

</div>

可见性能提升了快3倍。defaultdict用一个list工厂作为参数,同样可用于内建类型,比如long等。

除了实现的算法、架构之外,python提倡简单、优雅。所以正确的语法实践又很有必要,这样才会写出优雅易于阅读的代码。

二、语法最佳实践
字符串操作:优于python字符串对象是不可改变的,因此对任何字符串的操作如拼接,修改等都将产生一个新的字符串对象,而不是基于原字符串,因此这种持续的 copy会在一定程度上影响Python的性能:
        (1)用join代替 '+' 操作符,后者有copy开销;

        (2)同时当对字符串可以使用正则表达式或者内置函数来处理的时候,选择内置函数。如str.isalpha(),str.isdigit(),str.startswith((‘x', ‘yz')),str.endswith((‘x', ‘yz'))

        (3)字符格式化操作优于直接串联读取:

     str = "%s%s%s%s" % (a, b, c, d)  # efficient
     str = "" + a + b + c + d + ""  # slow

2. 善用list comprehension(列表解析)  & generator(生成器) & decorators(装饰器),熟悉itertools等模块:

(1) 列表解析,我觉得是python2中最让我印象深刻的特性,举例1:

   >>> # the following is not so Pythonic 
   >>> numbers = range(10)
   >>> i = 0 
   >>> evens = [] 
   >>> while i < len(numbers): 
   >>>  if i %2 == 0: evens.append(i) 
   >>>  i += 1 
   >>> [0, 2, 4, 6, 8] 

   >>> # the good way to iterate a range, elegant and efficient
   >>> evens = [ i for i in range(10) if i%2 == 0] 
   >>> [0, 2, 4, 6, 8]  
</div>

举例2:

def _treament(pos, element):
  return '%d: %s' % (pos, element)
f = open('test.txt', 'r')
if __name__ == '__main__':
  #list comps 1
  print sum(len(word) for line in f for word in line.split())
  #list comps 2
  print [(x + 1, y + 1) for x in range(3) for y in range(4)]
  #func
  print filter(lambda x: x % 2 == 0, range(10))
  #list comps3
  print [i for i in range(10) if i % 2 == 0]
  #list comps4 pythonic
  print [_treament(i, el) for i, el in enumerate(range(10))]

output:
24
[(1, 1), (1, 2), (1, 3), (1, 4), (2, 1), (2, 2), (2, 3), (2, 4), (3, 1), (3, 2), (3, 3), (3, 4)]
[0, 2, 4, 6, 8]
[0, 2, 4, 6, 8]
['0: 0', '1: 1', '2: 2', '3: 3', '4: 4', '5: 5', '6: 6', '7: 7', '8: 8', '9: 9']

</div>

没错,就是这么优雅简单。

   (2) 生成器表达式在python2.2引入,它使用'lazy evaluation'思想,因此在使用内存上更有效。引用python核心编程中计算文件中最长的行的例子:

f = open('/etc/motd, 'r')
longest = max(len(x.strip()) for x in f)
f.close()
return longest
</div>

这种实现简洁而且不需要把文件文件所有行读入内存。

 (3) python在2.4引入装饰器,又是一个让人兴奋的特性,简单来说它使得函数和方法封装(接收一个函数并返回增强版本的函数)更容易阅读、理解。'@'符号是装饰器语法,你可以装饰一个函数,记住调用结果供后续使用,这种技术被称为memoization的,下面是用装饰器完成一个cache功能:

import time
import hashlib
import pickle
from itertools import chain
cache = {}
def is_obsolete(entry, duration):
  return time.time() - entry['time'] > duration

def compute_key(function, args, kw):
  #序列化/反序列化一个对象,这里是用pickle模块对函数和参数对象进行序列化为一个hash值
  key = pickle.dumps((function.func_name, args, kw))
  #hashlib是一个提供MD5和sh1的一个库,该结果保存在一个全局字典中
  return hashlib.sha1(key).hexdigest()

def memoize(duration=10):
  def _memoize(function):
    def __memoize(*args, **kw):
      key = compute_key(function, args, kw)

      # do we have it already
      if (key in cache and
        not is_obsolete(cache[key], duration)):
        print 'we got a winner'
        return cache[key]['value']

      # computing
      result = function(*args, **kw)
      # storing the result
      cache[key] = {'value': result,-
              'time': time.time()}
      return result
    return __memoize
  return _memoize

@memoize()
def very_very_complex_stuff(a, b, c):
  return a + b + c

print very_very_complex_stuff(2, 2, 2)
print very_very_complex_stuff(2, 2, 2)
  


 

您可能想查找下面的文章:

  • python 获取网页编码方式实现代码
  • Python简单实现安全开关文件的两种方式
  • 判断网页编码的方法python版
  • python编码总结(编码类型、格式、转码)
  • Python编码爬坑指南(必看)
  • python编码最佳实践之总结
  • python编码最佳实践之总结
  • python中的编码知识整理汇总
  • python轻松实现代码编码格式转换
  • Python开发编码规范

相关文章

  • Django与遗留的数据库整合的方法指南
  • Python中实现对Timestamp和Datetime及UTC时间之间的转换
  • 利用PyInstaller将python程序.py转为.exe的方法详解
  • python实现简单socket程序在两台电脑之间传输消息的方法
  • python开启多个子进程并行运行的方法
  • python实现登陆知乎获得个人收藏并保存为word文件
  • Python中实现三目运算的方法
  • linux环境下安装pyramid和新建项目的步骤
  • Python3里的super()和__class__使用介绍
  • 用Python写飞机大战游戏之pygame入门(4):获取鼠标的位置及运动

文章分类

  • vbs
  • DOS/BAT
  • hta/htc
  • python
  • perl
  • VBA
  • ColdFusion
  • ruby
  • PowerShell
  • Lua
  • Golang
  • linux shell

最近更新的内容

    • 发布你的Python模块详解
    • 跟老齐学Python之让人欢喜让人忧的迭代
    • Python编程中用close()方法关闭文件的教程
    • python实现爬虫统计学校BBS男女比例(一)
    • Windows下Python使用Pandas模块操作Excel文件的教程
    • python中常用检测字符串相关函数汇总
    • python实现360皮肤按钮控件示例
    • python使用多线程不断刷新网页的方法
    • Python的Bottle框架中返回静态文件和JSON对象的方法
    • Python 时间处理datetime实例

关于我们 - 联系我们 - 免责声明 - 网站地图

©2020-2025 All Rights Reserved. linkedu.com 版权所有