楼主: lastwinner

[参考文档] Python 研究(Dive Into Python)

[复制链接]
论坛徽章:
484
ITPUB北京香山2007年会纪念徽章
日期:2007-01-24 14:35:02ITPUB北京九华山庄2008年会纪念徽章
日期:2008-01-21 16:50:24ITPUB北京2009年会纪念徽章
日期:2009-02-09 11:42:452010新春纪念徽章
日期:2010-03-01 11:04:552010数据库技术大会纪念徽章
日期:2010-05-13 10:04:272010系统架构师大会纪念
日期:2010-09-04 13:35:54ITPUB9周年纪念徽章
日期:2010-10-08 09:28:512011新春纪念徽章
日期:2011-02-18 11:43:32ITPUB十周年纪念徽章
日期:2011-11-01 16:19:412012新春纪念徽章
日期:2012-01-04 11:49:54
341#
 楼主| 发表于 2006-7-19 01:04 | 只看该作者
进一步阅读

使用道具 举报

回复
论坛徽章:
38
2013年新春福章
日期:2013-12-19 20:30:122013年新春福章
日期:2013-12-19 20:30:122013年新春福章
日期:2013-12-19 20:30:122013年新春福章
日期:2013-12-19 20:30:122013年新春福章
日期:2013-12-19 20:30:122013年新春福章
日期:2013-12-19 20:30:122013年新春福章
日期:2013-12-19 20:30:122013年新春福章
日期:2013-12-19 20:30:122013年新春福章
日期:2013-12-19 20:30:122013年新春福章
日期:2013-12-19 20:30:12
342#
发表于 2006-7-19 18:11 | 只看该作者
谢谢winner GG

使用道具 举报

回复
论坛徽章:
484
ITPUB北京香山2007年会纪念徽章
日期:2007-01-24 14:35:02ITPUB北京九华山庄2008年会纪念徽章
日期:2008-01-21 16:50:24ITPUB北京2009年会纪念徽章
日期:2009-02-09 11:42:452010新春纪念徽章
日期:2010-03-01 11:04:552010数据库技术大会纪念徽章
日期:2010-05-13 10:04:272010系统架构师大会纪念
日期:2010-09-04 13:35:54ITPUB9周年纪念徽章
日期:2010-10-08 09:28:512011新春纪念徽章
日期:2011-02-18 11:43:32ITPUB十周年纪念徽章
日期:2011-11-01 16:19:412012新春纪念徽章
日期:2012-01-04 11:49:54
343#
 楼主| 发表于 2006-7-20 01:37 | 只看该作者
最初由 anyoracle 发布
[B]谢谢winner GG [/B]


不客气

使用道具 举报

回复
论坛徽章:
484
ITPUB北京香山2007年会纪念徽章
日期:2007-01-24 14:35:02ITPUB北京九华山庄2008年会纪念徽章
日期:2008-01-21 16:50:24ITPUB北京2009年会纪念徽章
日期:2009-02-09 11:42:452010新春纪念徽章
日期:2010-03-01 11:04:552010数据库技术大会纪念徽章
日期:2010-05-13 10:04:272010系统架构师大会纪念
日期:2010-09-04 13:35:54ITPUB9周年纪念徽章
日期:2010-10-08 09:28:512011新春纪念徽章
日期:2011-02-18 11:43:32ITPUB十周年纪念徽章
日期:2011-11-01 16:19:412012新春纪念徽章
日期:2012-01-04 11:49:54
344#
 楼主| 发表于 2006-7-20 01:38 | 只看该作者
17.8. 小结
这一章中我们探讨了几个不同的高级技术。他们并不都适用于任何情况。

你现在应该能自如应用如下技术:

应用 正则表达式进行字符串替换。
将 函数当作对象,把它们存于列表中,把它们赋值给变量,并通过变量来调用它们。
构建 应用 lambda 的动态函数。
构建 闭合,将外部变量作为常量构建动态函数。
构建 生成器,进行逻辑递增操作并在每次调用时返回不同值的恢复执行函数。
抽象化,动态构建函数,构建闭合以及应用生成器能够使你的代码更加简单化、可读化、灵活化。 你需要在简洁和功能实现两方面进行平衡。

使用道具 举报

回复
论坛徽章:
484
ITPUB北京香山2007年会纪念徽章
日期:2007-01-24 14:35:02ITPUB北京九华山庄2008年会纪念徽章
日期:2008-01-21 16:50:24ITPUB北京2009年会纪念徽章
日期:2009-02-09 11:42:452010新春纪念徽章
日期:2010-03-01 11:04:552010数据库技术大会纪念徽章
日期:2010-05-13 10:04:272010系统架构师大会纪念
日期:2010-09-04 13:35:54ITPUB9周年纪念徽章
日期:2010-10-08 09:28:512011新春纪念徽章
日期:2011-02-18 11:43:32ITPUB十周年纪念徽章
日期:2011-11-01 16:19:412012新春纪念徽章
日期:2012-01-04 11:49:54
345#
 楼主| 发表于 2006-7-20 01:39 | 只看该作者
第 18 章 性能优化
18.1. 概览
18.2. 使用 timeit 模块
18.3. 优化正则表达式
18.4. 优化字典查找
18.5. 优化列表操作
18.6. 优化字符串操作
18.7. 小结
性能优化 (Performance tuning) 是一件多姿多彩的事情。Python 是一种解释性语言并不表示你不应该担心代码优化。但也不必 太 担心。

18.1. 概览
由于代码优化过程中存在太多的不明确因素,以至于你很难清楚该从何入手。

让我们从这里开始:你真的确信你要这样做吗? 你的代码真的那么差吗?值得花时间去优化它吗?在你的应用程序的生命周期中,与花费在等待一个远程数据库服务器,或是等待用户输入相比,运行这段代码将花费多少时间?

第二,你确信已经完成代码编写了吗? 过早的优化就像是在一块半生不熟的蛋糕上撒糖霜。你花费了几小时、几天(或更长) 时间来优化你的代码以提高性能,却发现它不能完成你希望它做的工作。那是浪费时间。

这并不是说代码优化毫无用处,但是你需要检查一下整个系统,并且确定把时间花在这上面是值得的。在优化代码上每花费一分钟,就意味着你少了增加新功能、编写文档或者陪你的孩子玩或者编写单元测试的一分钟。

哦,是的,单元测试。不必我说,在开始性能优化之前你需要一个完全的单元测试集。你需要的最后一件事情就是在乱动你的算法时引入新的问题。

使用道具 举报

回复
论坛徽章:
484
ITPUB北京香山2007年会纪念徽章
日期:2007-01-24 14:35:02ITPUB北京九华山庄2008年会纪念徽章
日期:2008-01-21 16:50:24ITPUB北京2009年会纪念徽章
日期:2009-02-09 11:42:452010新春纪念徽章
日期:2010-03-01 11:04:552010数据库技术大会纪念徽章
日期:2010-05-13 10:04:272010系统架构师大会纪念
日期:2010-09-04 13:35:54ITPUB9周年纪念徽章
日期:2010-10-08 09:28:512011新春纪念徽章
日期:2011-02-18 11:43:32ITPUB十周年纪念徽章
日期:2011-11-01 16:19:412012新春纪念徽章
日期:2012-01-04 11:49:54
346#
 楼主| 发表于 2006-7-20 01:39 | 只看该作者
谨记着这些忠告,让我们来看一些优化 Python 代码的技术。 我们要研究的代码是实施 Soundex 算法。 Soundex 是一种 20 世纪在美国人口普查中归档姓氏的方法。 它把听起来相似的姓氏归在一起,使得在即便错误拼写的情况下调查者仍能查找到。 Soundex 今天仍然因差不多的原因被应用着,当然现在用计算机数据库服务器了。 大部分的数据库服务器都有 Soundex 函数。
Soundex 算法有几个差别不大的变化版本。这是本章使用的:
  • 名字的第一个字母不变
  • 根据特定的对照表,将剩下的字母转换为数字:

    ·B、 F、 P 和 V 转换为 1。
    ·C、 G、 J、 K、 Q、 S、 X 和 Z 转换为 2.
    ·D 和 T 转换为 3.
    ·L 转换为 4.
    ·M 和 N 转换为 5.
    ·R 转换为 6.
    ·所有其他字母转换为 9.
  • 去除连续重复。
  • 去除所有 9 。
  • 如果结果都少于四个字符(第一个字母加上后面的三位字符),就以零补齐。
  • 如果结果超过四个字符,丢弃掉四位之后的字符。

比如,我的名字 Pilgrim 被转换为 P942695。 没有连续重复,所以这一步不需要做。然后是去除 9 ,剩下 P4265。 太长了,所以你把超出的字符丢弃,剩下 P426。
另一个例子: Woo 被转换为 W99,变成 W9,变成 W,然后以补零成为 W000 。

使用道具 举报

回复
论坛徽章:
484
ITPUB北京香山2007年会纪念徽章
日期:2007-01-24 14:35:02ITPUB北京九华山庄2008年会纪念徽章
日期:2008-01-21 16:50:24ITPUB北京2009年会纪念徽章
日期:2009-02-09 11:42:452010新春纪念徽章
日期:2010-03-01 11:04:552010数据库技术大会纪念徽章
日期:2010-05-13 10:04:272010系统架构师大会纪念
日期:2010-09-04 13:35:54ITPUB9周年纪念徽章
日期:2010-10-08 09:28:512011新春纪念徽章
日期:2011-02-18 11:43:32ITPUB十周年纪念徽章
日期:2011-11-01 16:19:412012新春纪念徽章
日期:2012-01-04 11:49:54
347#
 楼主| 发表于 2006-7-20 01:40 | 只看该作者
这是 Soundex 函数的第一次尝试:

例 18.1. soundex/stage1/soundex1a.py
如果您还没有下载本书附带的例子程序, 可以 下载本程序和其他例子程序。

[PHP]
import string, re

charToSoundex = {"A": "9",
                 "B": "1",
                 "C": "2",
                 "D": "3",
                 "E": "9",
                 "F": "1",
                 "G": "2",
                 "H": "9",
                 "I": "9",
                 "J": "2",
                 "K": "2",
                 "L": "4",
                 "M": "5",
                 "N": "5",
                 "O": "9",
                 "P": "1",
                 "Q": "2",
                 "R": "6",
                 "S": "2",
                 "T": "3",
                 "U": "9",
                 "V": "1",
                 "W": "9",
                 "X": "2",
                 "Y": "9",
                 "Z": "2"}

def soundex(source):
    "convert string to Soundex equivalent"

    # Soundex requirements:
    # source string must be at least 1 character
    # and must consist entirely of letters
    allChars = string.uppercase + string.lowercase
    if not re.search('^[%s]+$' % allChars, source):
        return "0000"

    # Soundex algorithm:
    # 1. make first character uppercase
    source = source[0].upper() + source[1:]
   
    # 2. translate all other characters to Soundex digits
    digits = source[0]
    for s in source[1:]:
        s = s.upper()
        digits += charToSoundex

    # 3. remove consecutive duplicates
    digits2 = digits[0]
    for d in digits[1:]:
        if digits2[-1] != d:
            digits2 += d
        
    # 4. remove all "9"s
    digits3 = re.sub('9', '', digits2)
   
    # 5. pad end with "0"s to 4 characters
    while len(digits3) < 4:
        digits3 += "0"
        
    # 6. return first 4 characters
    return digits3[:4]

if __name__ == '__main__':
    from timeit import Timer
    names = ('Woo', 'Pilgrim', 'Flingjingwaller')
    for name in names:
        statement = "soundex('%s')" % name
        t = Timer(statement, "from __main__ import soundex"
        print name.ljust(15), soundex(name), min(t.repeat())
。。。。。。。。。。
[/PHP]

使用道具 举报

回复
论坛徽章:
484
ITPUB北京香山2007年会纪念徽章
日期:2007-01-24 14:35:02ITPUB北京九华山庄2008年会纪念徽章
日期:2008-01-21 16:50:24ITPUB北京2009年会纪念徽章
日期:2009-02-09 11:42:452010新春纪念徽章
日期:2010-03-01 11:04:552010数据库技术大会纪念徽章
日期:2010-05-13 10:04:272010系统架构师大会纪念
日期:2010-09-04 13:35:54ITPUB9周年纪念徽章
日期:2010-10-08 09:28:512011新春纪念徽章
日期:2011-02-18 11:43:32ITPUB十周年纪念徽章
日期:2011-11-01 16:19:412012新春纪念徽章
日期:2012-01-04 11:49:54
348#
 楼主| 发表于 2006-7-20 01:41 | 只看该作者
进一步阅读

使用道具 举报

回复
论坛徽章:
484
ITPUB北京香山2007年会纪念徽章
日期:2007-01-24 14:35:02ITPUB北京九华山庄2008年会纪念徽章
日期:2008-01-21 16:50:24ITPUB北京2009年会纪念徽章
日期:2009-02-09 11:42:452010新春纪念徽章
日期:2010-03-01 11:04:552010数据库技术大会纪念徽章
日期:2010-05-13 10:04:272010系统架构师大会纪念
日期:2010-09-04 13:35:54ITPUB9周年纪念徽章
日期:2010-10-08 09:28:512011新春纪念徽章
日期:2011-02-18 11:43:32ITPUB十周年纪念徽章
日期:2011-11-01 16:19:412012新春纪念徽章
日期:2012-01-04 11:49:54
349#
 楼主| 发表于 2006-7-20 01:41 | 只看该作者
18.2. 使用 timeit 模块
关于 Python 代码优化你需要知道的最重要问题是,决不要自己编写计时函数。

为一个很短的代码计时都很复杂。 处理器有多少时间用于运行这个代码? 有什么在后台运行吗? 每个现代计算机都在后台运行持续或者间歇的程序。 小小的疏忽可能破坏你的百年大计,后台服务偶尔被 “唤醒” 在最后千分之一秒做一些像查收信件,连接计时通信服务器,检查应用程序更新,扫描病毒,查看是否有磁盘被插入光驱之类很有意义的事。 在开始计时测试之前,把一切都关掉,断开网络的连接。再次确定一切都关上后关掉那些不断查看网络是否恢复的服务等等。

接下来是计时框架本身引入的变化因素。 Python 解释器是否缓存了方法名的查找? 是否缓存代码块的编译结果? 正则表达式呢? 你的代码重复运行时有副作用吗? 不要忘记,你的工作结果将以比秒更小的单位呈现,你的计时框架中的小错误将会带来不可挽回的结果扭曲。

Python 社区有句俗语: “Python 自己带着电池。” 别自己写计时框架。 Python 2.3 具备一个叫做 timeit 的完美计时工具。

使用道具 举报

回复
论坛徽章:
484
ITPUB北京香山2007年会纪念徽章
日期:2007-01-24 14:35:02ITPUB北京九华山庄2008年会纪念徽章
日期:2008-01-21 16:50:24ITPUB北京2009年会纪念徽章
日期:2009-02-09 11:42:452010新春纪念徽章
日期:2010-03-01 11:04:552010数据库技术大会纪念徽章
日期:2010-05-13 10:04:272010系统架构师大会纪念
日期:2010-09-04 13:35:54ITPUB9周年纪念徽章
日期:2010-10-08 09:28:512011新春纪念徽章
日期:2011-02-18 11:43:32ITPUB十周年纪念徽章
日期:2011-11-01 16:19:412012新春纪念徽章
日期:2012-01-04 11:49:54
350#
 楼主| 发表于 2006-7-20 01:41 | 只看该作者
例 18.2. 介绍 timeit
如果您还没有下载本书附带的例子程序, 可以 下载本程序和其他例子程序。

>>> import timeit
>>> t = timeit.Timer("soundex.soundex('Pilgrim')",
...     "import soundex"   
>>> t.timeit()              
8.21683733547
>>> t.repeat(3, 2000000)   
[16.48319309109, 16.46128984923, 16.44203948912]
  timeit 模块定义了接受两个参数的 Timer 类。两个参数都是字符串。 第一个参数是你要计时的语句,这里你计时的是以'Pilgrim'参数调用 Soundex 函数。 传递给 Timer 的第二个参数是为第一个参数语句构建环境的导入语句。 从内部讲, timeit 构建起一个独立的虚拟环境, 手工地执行建立语句(导入 soundex 模块),然后手工地编译和执行被计时语句(调用 Soundex 函数)。
  一旦有了 Timer 对象,最简单的事就是调用 timeit(),它调用你的函数一百万次并返回所耗费的秒数。
  Timer 对象的另一个主要方法是 repeat(), 它接受两个可选参数。 第一个参数是重复整个测试的次数,第二个参数是每个测试中调用被计时语句的次数。 两个参数都是可选的,它们的默认值分别是 3 和 1000000。 repeat() 方法返回以秒记录的每个测试循环的耗时列表。


你可以在命令行使用 timeit 模块来测试一个已存在的 Python 程序,而不需要修改代码。在 http://docs.python.org/lib/node396.html 查看文档中关于命令行选项的内容。

注意 repeat() 返回一个时间列表。 由于 Python 计时器使用的处理器时间的微小变化(或者那些你没办法根除的可恶的后台进程),这些时间中几乎不可能出现重复。你的第一想法也许是说:“让我们求平均值获得真实的数据。”

事实上,那几乎是确定错误的。 你的代码或者 Python 解释器的变化可能缩短耗时,那些没办法去处的可恶后台进程或者其他 Python 解释器以外的因素也许另耗时延长。 如果计时结果之间的差异超过百分之几,太多的可变因素使你没法相信结果,如果不是这样则可以取最小值而丢弃其他结果。

Python 有一个方便的 min 函数可以把输入的列表返回成最小值:

>>> min(t.repeat(3, 1000000))
8.22203948912

timeit 模块只有在你知道那段代码需要优化时使用。 如果你有一个很大的 Python 程序并且不知道你的性能问题所在,到 查看 hotshot 模块。

使用道具 举报

回复

您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

TOP技术积分榜 社区积分榜 徽章 团队 统计 知识索引树 积分竞拍 文本模式 帮助
  ITPUB首页 | ITPUB论坛 | 数据库技术 | 企业信息化 | 开发技术 | 微软技术 | 软件工程与项目管理 | IBM技术园地 | 行业纵向讨论 | IT招聘 | IT文档
  ChinaUnix | ChinaUnix博客 | ChinaUnix论坛
CopyRight 1999-2011 itpub.net All Right Reserved. 北京盛拓优讯信息技术有限公司版权所有 联系我们 未成年人举报专区 
京ICP备16024965号-8  北京市公安局海淀分局网监中心备案编号:11010802021510 广播电视节目制作经营许可证:编号(京)字第1149号
  
快速回复 返回顶部 返回列表