Labels

Monday, August 22, 2011

Learning Python 3rd edition--1

1.    Python Object Types

Python is dynamically typed (it keeps track of types for you automatically instead of requiring declaration code), but it is also strongly typed (you can only perform on an object operations that are valid for its type).

Every object in Python is classified as immutable (unchangeable) or not. In terms of the core types, numbers, strings, and tuples are immutable; lists and dictionaries are not (they can be changed in-place freely). Among other things, immutability can be used to guarantee that an object remains constant throughout your program.

1.1      String


S # A 4-character string

'Spam'

>>> S[1:3] # Slice of S from offsets 1 through 2 (not 3)

'pa'

Their general form, X[I:J], means “give me everything in X from offset I up to but not including offset J.” The result is returned in a new object. In a slice, the left bound defaults to zero, and the right bound defaults to the length of the sequence being sliced. This leads to some common usage variations:

>>> S[1:] # Everything past the first (1:len(S))

'pam'

>>> S # S itself hasn't changed

'Spam'

>>> S[0:3] # Everything but the last

'Spa'

>>> S[:3] # Same as S[0:3]

'Spa'

>>> S[:-1] # Everything but the last again, but simpler (0:-1)

'Spa'

>>> S[:] # All of S as a top-level copy (0:len(S))

'Spam'



Finally, as sequences, strings also support concatenation with the plus sign (joining two strings into a new string), and repetition (making a new string by repeating another):

>>> S

'Spam'

>>> S + 'xyz' # Concatenation

'Spamxyz'

>>> S # S is unchanged

'Spam'

>>> S * 8 # Repetition

'SpamSpamSpamSpamSpamSpamSpamSpam'

1.2      List


lists support all the sequence operations we discussed for strings; the only difference is that results are usually lists instead of strings. For instance, given a three-item list:

>>> L = [123, 'spam', 1.23] # A list of three different-type objects

>>> len(L) # Number of items in the list

3

we can index, slice, and so on, just as for strings:

>>> L[0] # Indexing by position

123

>>> L[:-1] # Slicing a list returns a new list

[123, 'spam']

>>> L + [4, 5, 6] # Concatenation makes a new list too

[123, 'spam', 1.23, 4, 5, 6]

>>> L # We're not changing the original list

[123, 'spam', 1.23]



List Comprehensions

In addition to sequence operations and list methods, Python includes a more

advanced operation known as a list comprehension expression, which turns out to be

a powerful way to process structures like our matrix. Suppose, for instance, that we

need to extract the second column of our sample matrix. It’s easy to grab rows by

simple indexing because the matrix is stored by rows, but it’s almost as easy to get a

column with a list comprehension:

>>> col2 = [row[1] for row in M] # Collect the items in column 2

>>> col2

[2, 5, 8]

>>> M # The matrix is unchanged

[[1, 2, 3], [4, 5, 6], [7, 8, 9]]

List comprehensions derive from set notation; they are a way to build a new list by running an expression on each item in a sequence, one at a time, from left to right. List comprehensions are coded in square brackets (to tip you off to the fact that they make a list), and are composed of an expression and a looping construct that share a variable name (row, here). The preceding list comprehension means basically what it says: “Give me row[1] for each row in matrix M, in a new list.”

List comprehensions can be more complex in practice:

>>> [row[1] + 1 for row in M] # Add 1 to each item in column 2

[3, 6, 9]

>>> [row[1] for row in M if row[1] % 2 == 0] # Filter out odd items

[2, 8]

1.3      Dictionaries


Dictionaries, the only mapping type in Python’s core objects set, are also mutable: they may be changed in-place, and can grow and shrink on demand, like lists.

dictionaries are not sequences, they don’t maintain any dependable left-to-right order. This means that if we make a dictionary, and print it back, its keys may come back in a different order than how we typed them:

>>> D = {'a': 1, 'b': 2, 'c': 3}

>>> D

{'a': 1, 'c': 3, 'b': 2}

·       if we do need to impose an ordering on a dictionary’s items?

One common solution is to grab a list of keys with the dictionary keys method, sort that with the list sort method, and then step through the result with a Python for loop:

1.4      Tuple


(1,2,3,4)

They are immutable sequences. Tuples are not generally used as often as lists in practice, but their immutability is the whole point. If you pass a collection of objects around your program as a list, it can be changed anywhere; if you use a tuple, it cannot.

1.5      Files


A file’s contents are always a string of bytes to your script, regardless of the type of data the file contains.

有一个c++程序在一个机器上运行正常,到另一个上就crash了,有可能是些什么问题

系统硬件是否兼容,比如cpu指令集?
操作系统是否一样,windows/linux,已及小版本
系统环境变量是否一致
是否少了第三方的动态库?
还有很多。。。

版本、IDE选择及编码解决方案

转载一块努力的牛皮糖”:http://www.cnblogs.com/yuxc/引言
在这里我假设你已经看完了一篇Python教程,基本熟悉了Python的结构和语法,在命令行下的Python互动环境中尝试过大部分Python的语句,觉得Python是个不错的语言准备继续下去。那么本篇文章会就Python实际运用中相关工具的选择,包括IDE,调试套件,第三方库管理工具这些进行介绍。另外还会对某些中文环境下容易遇到的问题,例如unicode编码解码的问题进行说明。本文主要是针对 Windows 环境下的 Python 开发进行说明。文章的目的是为了分享些我觉得很有用的经验和例子,若发现文中有疏漏之处请务必联系我。谢谢。

Python 语言介绍
Python 是一个近些年在开始流行起来的计算机编程语言。根据Python官网上的简介,Python主要特性包括跨平台,免费,简单且容易维护。就我个人理解来说,Python是一门适合大部分人的语言,因为各种类型的第三方库都有,所以像简单桌面程序,动态网站开发,图像处理,表格处理,甚至自动发帖机这些小应用在简单的学习后,不需要很深厚的编程经验的人应该都能自己做出来。

Python 版本选择,其他发行版
Python 2 与 3
Python 2 和 3 系列的选择可能是比较让人烦躁的事情。其实区别很简单:Python 3.x 各个方面都更好,但语法与 Python 2.x 很大部分不兼容。Python 2.x 已经停止继续开发。但是目前很多第三方库仍然不支持 Python 3 , 文章后面介绍的很多工具譬如 ipython 目前也是仅支持 Python 2.6 的。
我建议现在选择 Python 2.6.5 ,因为目前大部分第三方库和工具对2.6都有简单的安装包,不需要自己做太多处理。

发行版
目前在 Windows 下除了官方提供的安装版外,还有:
ActivePython ,这个与官方版本的区别在于提供了额外的库和文档,并且自动设置了PATH环境变量(后文会详细提到)
Python(x,y),这个是我一直用并且推荐给别人用的版本。从名字就能看出来这个发行版附带了科学计算方面的很多常用库,另外还有大量常用库比如用于桌面软件界面制作的 PyQt, 还有文档处理,exe文件生成等常用库。另外的还有大量的工具如IDE,制图制表工具,加强的互动shell之类。很多下文提到的软件在此发行版中都有附带。其他方面,Python(x, y)还附带了手工整理出的所有库的离线文档,每个小版本升级都提供单独的补丁。总的来说是很用心维护的一个发行版,十分建议安装这个版本。

开发相关工具
在真正着手开发之前,你应该在下载一份离线的文档。在这个页面下载一份 HTML 格式的,解压出来其中 index.html 就是文档主页面。页面左边的 Quick Search 是离线也可以使用的,有对函数功能有疑惑或者要查询模块的时候就能在这里查看。

选择 PyDev 作为 IDE
Python 集成开发环境的选择好像一直以来也是一个很难抉择的问题。在尝试过很多个工具后我发现基于 Eclipse 的 PyDev 绝对是功能最为完整的一个 IDE 。除了断点调试之外,PyDev 的代码自动补全可能是现在这类 IDE 中最强力的。
如果你安装了 Python(x, y) 的话,PyDev 就已经在你的机器上了。如果没有的话请按照这篇文章来进行安装。
设置上有一些需要注意的地方。首先在打开 PyDev ,打开菜单中
Window -> Preferences
,在弹出对话框中左边找到
PyDev -> Editor -> Code Completion
。这里可以设置代码自动补全的相关信息。可以降低 Autocompletion delay 来更早的提示代码,并且将 Request completion on 系列尽可能勾上,让 PyDev尽可多的提示代码。
之后再找到
Interpreter Python
选项卡,这里可以设置所谓 Forced Buildins,可以强制引入某些第三方库从而完成代码补全。就我的经验来看大部分第三方库在这样设置后都能进行基本的补全。具体的做如图中,选择到对应的选项卡,点击 New,并输入你需要的模块名字即可。
Forced Buldins设置
设置后总体效果绝对是同类IDE中比较好的:
Eclipse 补全效果

IPython 替代 Python Shell
在学习 Python 的时候应该都接触过 Python 的 Shell,能够输入 Python 语句并且立即返回结果。而 IPython就是一个豪华加强版的 Python Shell。如果你安装了 Python(x, y) 的话,那 IPython 已经在你的机器上了。如果没有的话那么请在这里下载 Windows Installer 进行安装。在安装这个之后还需要安装 pyreadline 让 IPython 开启高亮和自动补全功能。之后你在命令行下需要 python 的时候改为输入 ipython就能使用它了。开启 IPython 看看,首先感觉的不同应该是这个是有颜色的。我们来看看它提供的一些基础而实用的功能吧。首先是自动补全,一种是简单的关键字补全,另外一种是对象的方法和属性补全。作为例子,我们先引入sys模块,之后再输入 sys.(注意有个点),此时按下 tab 键,IPython 会列出所有 sys 模块下的方法和属性。因为是在互动模式下进行的,此时的 Python 语句实实在在的被执行了,所以对普通 object 的补全也是很完好的。
IPython
接着上面的例子,我们输入sys?,这样会显示出sys模块的 docstring及相关信息。很多时候这个也是很方便的功能。
IPython 另外还有很多方便的功能,可以自己参阅文档来发掘。这里另外介绍一个很神奇的功能。如果你的程序是由命令行开始执行的,即在命令行下输入python foo.py
(大部分 Python 程序都是),那么你还可以利用 IPython 在你的程序任意地方进行断点调试!在你程序中任意地方,加入如下语句:
from IPython.Shell import IPShellEmbed  IPShellEmbed([])()  
再和平常一样运行你的程序,你会发现在程序运行到插入语句的地方时,会转到 IPython 环境下。你可以试试运行些指令,就会发现此刻 IPython 的环境就是在程序的那个位置。你可以逐个浏览当前状态下的各个变量,调用各种函数,输出你感兴趣的值来帮助调试。之后你可以照常退出 IPython,然后程序会继续运行下去,自然地你在当时 IPython 下执行的语句也会对程序接下来的运行造成影响。
这个方法我实在这里看到的。想象一下,这样做就像让高速运转的程序暂停下来,你再对运行中的程序进行检查和修改,之后再让他继续运行下去。这里举一个例子,比如编写网页 bot ,你在每取回一个页面后你都得看看它的内容,再尝试如何处理他获得下一个页面的地址。运用这个技巧,你可以在取回页面后让程序中断,再那里实验各种处理方法,在找到正确的处理方式后写回到你的代码中,再进行下一步。这种工作流程只有像 Python 这种动态语言才可以做到。

pip 管理第三方库
Python 的一大优势就是有极为大量的第三方库,包括各个方面的引用。然而安装第三方库对没有掌握方法的同学来说会变得很让人烦恼。事实上 Python 第三方库的安装和管理有着一个一个唯一正确的做法,这个做法要求你什么其他的都不用干,只要输入你要安装库的名字就可以了。
setuptools 也包在 Python(x, y) 当中。如果没有的话,要首先先安装 setuptools ,这个其实就是一个安装第三方库的软件。选择对应版本的 Windows Installer 进行下载和安装后,打开一个命令行窗口,输入:
easy_install pip  
如果提示找不到程序,那么说明你当前没有设定好环境变量。安装官方提供的 Python 安装包的话肯定会有这个问题,而且很可能暂时不会修正,这就是牛逼程序员的倔强。具体做法是 右键我的电脑 - 属性 - 高级系统设置 - 环境变量 - 将
C:\python2*\Scripts
加入到 PATH 那一组当中。这样做的效果就是在任何地方的命令行下输入命令,那么系统会额外查找我们设定的那个目录中的内容。之后再执行上面的命令,装好了以后我们就要弃用 setuptools,转投 pip。要安装任何一个库,你只要找到他的名字(不需要版本号),用 pip 安装即可。譬如安装 django,那么输入如下命令即可:
pip install django  
其实之前easy_install跟 pip效用是类似的,都是在官方的第三方库索引 PyPI 查询信息并进行下载和安装。pip 的优势在于支持更高级的功能,譬如虚拟环境,安装失败不会残留破损的库,更重要的是 pip 还可以进行卸载。输入下面命令就能卸载一个之前由 pip 进行安装的库。继续上面的例子,现在要卸载 django:
pip uninstall django  
这是 setuptools 所缺失的功能。需要额外说明的是大部分纯 Python 的库都能用这个方法在 Windows 下装上,但是需要编译 C 语言模块的一般都不太可能成功。遇到这种情况,在相应的库德站点上找找有没有对应的 Windows 安装包。

Winpdb
如果你使用的 PyDev 的话那么用其自带的断点调试应该就可以了。Winpdb则是为用其他简单编辑器进行 Python 开发的用户提供一个熟悉的调试环境。Winpdb不出意料的也在 Python(x, y)当中。所以如果装上 Python(x, y) 你可以不断发掘里面附带的优秀工具。使用方法很简单,假设程序名为 foo.py,那么在命令行中输入:
winpdb foo.py  
之后会弹出窗口,也就是一个大家都熟悉的 debug 图形界面。需要注意的是这里需要点击想要设置断点的行,点击 F9 设置断点,然后该行底色会变为红色,如下图所示。
Winpdb

编码问题
作为中文用户,初学 Python 最容易碰到的问题估计就是编码问题了。明明英文的都可以用到中文的时候就要出问题,而且出错信息难以理解,想要解决问题又不知道从何开始。幸运的是编码问题通过预防性的措施是很好避免的。下面从几个方面来讲讲 Python 中处理中文及 Unicode 容易碰到的问题。

Unicode 编码基础
这里非常简单的讲一下编码知识,此部分表述可能不太准确,如果你对 Unicode 更为了解的话请联系我帮忙纠正。
你可以想象 Unicode 是一个很大的表,里面有着世界上所有的文字的个体,如英文中的字母,中文的汉字。事实上 Unicode 标准中每一个字都有一个唯一对应的编号,好比说 '中'字 对应十六进制 0x4E2D,而字母 'a' 对应的是十六进制 0x0061。这个编号是由 Unicode Consortium 这个组织来确定的。 如果说用这个编码来对应字符来用于表示字符,理论上是可以的,这样的话就是每一个数字编号能对应一个字符。
而实际情况中,不是每篇文章都用得到世界上所有的字符。譬如一篇英文文章就只有英文字母加上一些符号,用 Unicode 来进行存储的话每个字符要浪费太多的空间。所以就有各种类型的编码产生。编码我们这里可以理解就是将一部分的 Unicode (比如说所有的中文,或者所有的日文)字符,以某种方式确定另外一个符号来代表他。中文常用编码有 UTF8 和 GBK,仍然以 '中'字 为例, UTF8 编码将对应 '中'字 的 Unicode 编号
0x4E2D
拆成三个的编号的组合,
[0xE4, 0xB8, 0xAD]
,只有这几个连在一起的时候才会被作为一个 '中'字 显示出来;作为对比,GBK 编码将 '中'字 对应的 Unicode 编号
0x4E2D
编码成为两个编号的组合
[0xD6, 0xD0]
,在 GBK 编码环境下只有这两个编号一起时,才会显示为 '中'字。
上面的例子中,如果把 UTF8 编码后的
[0xE4, 0xB8, 0xAD]
放到 GBK 环境下来显示会怎样?这几个编号跟 '中'字 在 GBK 下的编码
[0xD6, 0xD0]
,不同,则显然不会显示为 '中'字。这三个字符会跟排在其前后的字符一起,按照 GBK 的编码规则找有没有对应的字符。结果有可能显示出一个毫不相关的字符,有时候为符号或者干脆不显示,这种情况就算产生了乱码。

Python 2.x 中的 String 与 Unicode
在 Python 2.x 中是有两种字串符相关类型的,分别为 String 和 Unicode,两者提供的接口非常类似,有时候又能自动转换,蛮容易误导人的。在 Python 3 中 这两个类型分别用 Bytes 和 String 替代了。这个名字更能说明两者的本质:Python 2.x 中的 String 中存储的是没有编码信息的字节序列,也就是说 String 中存储的是已经编码过后的序列,但他并不知道自身是用的哪种编码。相反的 Unicode 中存储的是记载了编码的字串信息,其中存储的就是相应字符的 Unicode 编号。在这里用程序来说明,我们建立一个简单的脚本名字为
encoding.py
,代码如下:
#!/usr/bin/python  # -*- coding: utf-8 -*-    strs = "这是中文"  unis = "这也是中文".decode("utf8")    print strs[0:2]  print unis[0:2].encode('gbk')    print len(strs)  print len(unis)  
前面两行后面会解释到,就是限定运行环境以及该脚本文件的编码格式。此脚本在这里可以下载,如果你要自己写的话请务必确保脚本的编码是 utf8 而不是别的。在 Windows 下的运行结果在这里,我觉得正好能说明问题:
C:\SHARED\Dev\scripts>encoding.py  杩  这也  12  5  
这里需要说明,我们的程序是 UTF8 编码,主要意义是该程序中的所有直接写出来的字串符(用"", ''括起来的字串符)是运用 UTF8 格式编码的;然而 Windows 下的命令行是 GBK 环境。这里strs是一个 String。事实上在 Python 2.x 中直接写在程序中的字串符,其类型都是
String(这里不考虑 string literal)。我们先直接输出 strs[0:2],得到的是一个乱码字符(这个字符只是碰巧凑成是一个字)。如上面说的,String中存储的是没有编码信息的字串序列,这里就是将
strs中前两个编号取出并尝试显示。由于命令行环境为 GBK 编码,这里对应的字碰巧凑成了一个字,但是跟原本的字没有任何关系。unis是由一个String调用decode()方法得到,这正是在 Python 2.x 中取得Unicode的最基本的方式。由于String并不知道它本身是由什么编码格式来进行的编码,这里是我们的责任来确定他原来是用哪种编码方式进行编码。我们知道代码中的编码格式是 UTF8,所以我们可以用调用String的 decode()方法来进行反编码,也就是解码, 把字串符从某种编码后的格式转换为其唯一对应的 Unicode 编号。unis为解码获得的结果,其在 Python 2.x 中对应类型就是Unicode,其中存储的就是 每个字符对应的 Unicode 编号。我们尝试输出unis的前两个字符,在这里我们调用了Unicode的 encode()方法。这就是编码的过程。我们知道 Windows 命令行下的编码是 GBK,只有采用 GBK 编码的字符才能正确显示。所以在这里我们通过调用Unicode的encode()方法,将 unis中存储的 Unicode 编号 按照 GBK 的规则来进行编码,并输出到屏幕上。这里我们看到这里正确的显示了unis中的前两个字符。要注意的是在命令行中直接printUnicode的话 Python 会自动根据当前环境进行编码后再显示,但这样掩盖了两者的区别。建议总是手动调用encode和 decode方法,这样自己也会清楚一些。后面两者长度的差别也是佐证我们之前的例子。
strs中存储的是 UTF8 编码后的编号序列,上面看到一个中文字符在 UTF8 编码后变成三个连续的,所以 strs长度为 3x4 = 12。你可以想象 strs中存放的并不是中文,而是一系列没有意义的比特序列;而unis中存储的是对应的中文的 Unicode 编码。我们知道每一个字符对应一个编号,所以五个字对应五个编号,长度为 5。

避免,和解决编码产生的问题
了解了 Python Unicode 编码解码的这些概念后,我们来看看如何尽量的避免遇到让人烦心的编码问题。
首先如果你的代码中有中文,那么一定要务必声明代码的编码格式。根据 PEP-0263 中的介绍,在程序的最开始加上以下两行注释就能确定编码:
#!/usr/bin/python  # -*- coding: utf-8 -*-  
其中utf-8就是指定的编码格式。事实上你应该总是使用 UTF8 作为你 Python 程序的编码格式,因为未来的 Python 3 所有文件都将默认以 UTF8 编码。另外除了声明,你必须确定你用来编辑 Python 程序的编辑器是不是真的以 UTF8 编码来存储文件。
之后就是养成关于编码解码的好习惯。当你的程序有 String作为输入时,应该尽早的将其转换为 Unicode,再在程序中进行处理。再输出的时候,也要尽可能玩,直到最后输出的时刻才将 Unicode编码为所需编码格式的 String进行输出。同样的你必须保持你程序内部所有参与运算的字串都是 Unicode格式。很多著名的 Python 库例如 django 就是采用的这种方式,效果也蛮好。千万不要依赖 Python 自己进行两者之间的转换,也不要将 String和 Unicode放在一起运算,这些行为一方面十分容易引起错误,另一方面在 Python 3 中已经无法再现。虽说确定 String的编码格式是程序员的责任,但有时候你真的不知道有些字串符到底是什么编码的。这里有一个神奇 chardet 能够帮助你。以下是摘自其页面上的例子,很好了说明了它的作用:读入任意一串字符,猜测其编码格式,并且给出猜测的确信度。
>>> import urllib  >>> urlread = lambda url: urllib.urlopen(url).read()  >>> import chardet  >>> chardet.detect(urlread("http://google.cn/"))  {'encoding': 'GB2312', 'confidence': 0.99}    >>> chardet.detect(urlread("http://yahoo.co.jp/"))  {'encoding': 'EUC-JP', 'confidence': 0.99}    >>> chardet.detect(urlread("http://amazon.co.jp/"))  {'encoding': 'SHIFT_JIS', 'confidence': 1}    >>> chardet.detect(urlread("http://pravda.ru/"))  {'encoding': 'windows-1251', 'confidence': 0.9355}  
如果 confidence 非常低的话或者 chardet 直接报错,多半是字串经过多次错误编码解码,要从别的地方找办法解决问题。
如果上面的介绍还不能让你理解 Unicode 的概念,这里还有几篇关于这个问题的文章:
介绍 Unicode 的两篇文章 [1], [2]。关于 Unicode 有更为详细的解释。
Unicode In Python, Completely Demystified 特别针对 Python 下的 Unicode 处理进行详细的讲解。

Python教程,电子书及相关资源


一些流行的Python教程有:

Dive into Python 面向有一定编程基础的同学。另外还有Dive into Python 3,针对Python3的教程。

Learn Python The Hard Way,书中主要是通过各种练习来进行学习,面向完全没有编程经验的同学。

Invent Your Own Computer Game With Python,让你一上手就做个游戏出来的教程,厉害。

The Python Tutorial,官方文档中的教程,正统而完整。

其他相关资源

Python做科学计算
这个把Python(x,y)里面所有的模块基本上都讲了一遍,我觉得外国人肯定都希望这个有个英文版的。

PyMOTW
这个名字看起来像个Python(其实它还真的是一个...),但他总体来说其实是一份文档, "Python每周一个模块"。作者持续几年每周介绍一个Python标准库中的库。你可以把他看做是一个Python标准库文档的一个很棒的补充,当你看标准库中的介绍看的云里雾里的时候,不妨来这边找找相应的介绍。因为这里的例子给的很全,而且基本上你用的到的偏门的库这里都有介绍哦。另外一个好消息是PyMOTW有一份很棒中文翻译版 

reddit.com/r/python python.org planet
Python 相关的文章和资源。就我个人经历来说,每次都能在这里看到很多有用的东西。

python 入门书籍推荐
  

python 学习手册第3版本

作为python的镐头书来说这个书还算是不错的,浅显易懂,基本上各个知识点都有讲到,代码的排版也还不错,对初学者的帮助很大,我个人觉得通过这本书能够让你对python有整体的了解


python 核心编程

python核心编程是本偏向应用的书籍,里面有很多相关的例子,对一些标准库都有讲解,如果你有点基础的话,或者通过上面的python学习手册对python有大概的了解的话,想具体的使用python来完成一些应用的话,这本书不能错过了。


可爱的python

看编程的书第一次看到如此清新,别具一格的。读了前十几页,不断地与自己的学习经历产生共振。 经鉴定:此书乃真科学,真技术。


python unix和linux系统指南

这本书卖的很火,之前一直缺货,好不容易看到不缺货就买了,买完了写评论时又发现缺货了。 刚到货,初看下还不错,准备好好研究下。发现这本书籍对于linux,unix系统管理员特别合适,里面讲解了很多用python来完成系统的工作


python源码剖析

拿到书以后因为工作需要就看了讲解线程机制那一张,讲得很详细。作者不是简单的阐释源码的意思,而是更深层次的去探讨为什么那么做,这点难能可贵。在国人出的书里能有这种深度的探讨的作品真的很少。 如果你对C和PYTHON都比较了解又想深入学习的话,那这本书是一个不错的选择。


python网络编程基础

有些内容涉及到网络协议,是python网络编程入门的好教材,如果你想用python来处理一些网络应用方面的话,这本书对你帮助很大

  
Python电子书本地收集 -- 啄木鸟空间发布

精读类

Thursday, August 18, 2011

计算字符串的相似度

计算字符串的相似度

我们定义了一套操作方法来把两个不相同的字符串变得相同,具体的操作方法为:

1. 修改一个字符 (如 把“a”替换为“b”)。

2. 增加一个字符 (如把“abdd”变为“aebdd”)。

3. 删除一个字符(如把“travelling”变为“traveling”)。

比如,对于“abcdefg”和“abcdef”两个字符串来说,我们认为可以通过增加/减少一个“g 的方式来达到目的。上面的两种方案,都仅需要一次操作。把这个操作所需要的次数定义为两个字符串的距离,而相似度等于“距离+1”的倒数。



分析与解法

1. 一步操作之后,再将A[2, , lenA]B[1, , lenB]变成相同字符串。

2. 一步操作之后,再将A[1, , lenA]B[2, , lenB]变成相同字符串。

3. 一步操作之后,再将A[2, , lenA]B[2, , lenB]变成相同字符串。



int CalculateStringDistance(string strA, int pABegin, int pAEnd, string strB,int pBBegin, int pBEnd){

      if(pABegin>pAEnd){

            if(pBBegin>pBEnd)

                  return 0;

            else

                  return pBEnd-pBBegin+1;

     

      }

      if(pBBegin > pBEnd)

      {

            if(pABegin > pAEnd)

                  return 0;

            else

                  return pAEnd – pABegin + 1;

      }



      if(strA[pABegin]==strB[pBBegin])

return CalculateStringDistance(strA, pABegin+1, pAEnd, strB, pBBegin+1, pBEnd);

      else{

int t1 = CalculateStringDistance(strA, pABegin + 1, pAEnd, strB, pBBegin + 2, pBEnd);

int t2 = CalculateStringDistance(strA, pABegin + 2, pAEnd, strB, pBBegin + 1, pBEnd);

int t3 = CalculateStringDistance(strA, pABegin + 2, pAEnd, strB, pBBegin + 2, pBEnd);

            return minValue(t1,t2,t3) + 1;     
       }
}




Wednesday, August 17, 2011

大于6的素数,证明为什么相邻素数中间的数能够被6整除

大于6的素数,证明为什么相邻素数中间的数能够被6整除

比如
11,12,13
17,18,19
29,30,31
41,42,43

assume it cannot be divided by 6, the middle one can only be 6x + 1, 6x+2,6x+3,6x+4, or 6x+5.
Exclude one by one
1) 6x+1
Then the less Prime number should be 6x, conflict
2) 6x+2
Then the large Prime num should be 6x+3, conflict
3) 6x+3
Then the less Prime number should be 6x+2, conflict
4) 6x+4
Then the less Prime number should be 6x+3, conflict
4) 6x+5
Then the large Prime number should be 6x+6 conflict
So, it can be divided by 6.

however, it is not true if there are multiple numbers between two prims such
13, 14, 15, 16, 17

Tuesday, August 16, 2011

Polymorphism, virtual function, pure virtual function, virtual table

Polymorphism is the ability of one method to have different behavior depending on the type of object it is being called on or the type of object being passed as a parameter. 
Polymorphism is based on dynamic binding and virtual functions.  

Virtual function is a function whose behavior can be overridden within an inheriting class by a function with the same signature. The redefined the method from derived class can be accessed through a pointer or reference from base class. If virtual function called through reference or pointer to a base class, then this call will be resolved at run time and dynamic binding will happen. 

Pure virtual function: typically have a declaration (signature) and no definition (implementation).

Abstract class is a class that has one or more pure virtual member functions. You cannot make an object (instance) of an ABC
 
For all practical purposes, virtual functions aren't inlined.
That's because "inline" means "during compilation, replace the call site with the body of the called function," but "virtual" means "wait until runtime to see which function is called."


Virtual Table and Virtual Table Pointer

The implementation of virtual functions depends on "virtual table “.Each class in a program that declares or inherits virtual functions has its own vtbl, and the entries in a class's vtbl are pointers to the implementations of the virtual functions for that class. Each object of this class carries with it a hidden data member “virtual table pointer” that points to the virtual table for that class. When a virtual function is called, the actual function called is determined by following the object's vptr to a vtbl and then looking up the appropriate function pointer in the vtbl. Whenever there is a virtual function call, the v-table is used to resolve to the function address.

3 persons, how can they know the average salary of the three persons without knowing other person's salary

3 persons, how can they know the average salary of the three persons but without knowing other persons' salary. [bloomberg]
让每个人随机写一个数,传给下一个人。下一个人把自己薪水和这个数字相加传给下一个人,下一个人把这数字减去自己写的数字然后报出来。三个数字相加除以三就是三人平均薪水。
R1, R2, R3 is the random number written by person 1, 2, 3

Steps
P1
P2
P3
1
R3
R1
R2
2
R3+S1-R1
R1+S2-R2
R2+S3-R3
3
((R3+S1-R1)+(R1+S2-R2)+(R2+S3-R3))/3=(S1+S2+S3)/3

or
P1 produce a random number R1, pass S1+R1 to P2, P2 pass S1+R1+S2 to P3, P3 pass S1+R1+S2+S3 back to P1. Then P1 abstract R1, speak out R1+R2+R3/3

Monday, August 15, 2011

Given 12 coins, identify the special one in three weighings(转)

Occam's razor states a preference for simple theories. "Accept the simplest explanation that fits the data".
12 coins. One of them is heavier or lighter than the rest.
Identify this coin and whether it is heavier or lighter in three weighings.

In general, given N coins, at least how many times are needed to identify this coin and whether it is heavier or lighter ?
关键就是每次称都有三种结果:左边重,右边重,两边一样重。那理论上N次操作后可以用3^N种状态。那么12个球也就需要3次就够了。而3次最大可以称27球。
每次操作的关键就是让三种结果的概率尽可能相等。

这种题最简单的解法就是逆推。
最后一步你肯定是要确定特殊硬币在某三个硬币之间(这样才能一次找出),然后前两步自然就是找出这三个硬币。
12个硬币组合方式也就那么多,自然就会分成四拨,每拨三个。四拨三个随便拿两拨称,不一样就说明特殊硬币不在剩下的两拨里面。在剩下两拨里面随便拿一拨(肯定不含特殊硬币)跟最开始选择的两拨里重的那拨称(轻的同理)。如果不一样,说明特殊硬币重了,且在最开始两拨里重的那拨里面。然后一次称重就可找出。如果一样,就说明特殊硬币轻了,且在最开始两拨里轻的那拨里面。同样一次称重可找出。
如果第一次称重重量一样,说明特殊硬币在剩余两拨里面,同理可得。
Given 8 coins, how to identify the heavier one in 2 weighing?
123, 456, 78
if 123 > 456
    then weigh any two from 123, find the heavier one
else if 456 > 123
    do same as above
else
    weigh 78, find the heavier one

Thursday, August 11, 2011

binary search tutorials

binary search http://www.topcoder.com/tc?module=Static&d1=tutorials&d2=binarySearch
To wrap it up, here's an STL-driven snippet which solves the problem:
int getMostWork( vector  folders, int workers ) {
   int n = folders.size();
   int lo = *max_element( folders.begin(), folders.end() );
   int hi = accumulate( folders.begin(), folders.end(), 0 );

   while ( lo < hi ) {
      int x = lo + (hi-lo)/2;

      int required = 1, current_load = 0;
      for ( int i=0; i<n; ++i ) {
         if ( current_load + folders[i] <= x ) {
            // the current worker can handle it
            current_load += folders[i];
         }
         else {
            // assign next worker
            ++required;
            current_load = folders[i];               
         }
      }

      if ( required <= workers )
         hi = x;
      else
         lo = x+1;
   }

   return lo;
}

Tuesday, August 9, 2011

Install and configure ECB

转自:http://tigersoldier.ycool.com/post.1888910.html
Install and configure ECB
ecb是用来浏览代码用的,可以列出代码中的函数,写大规模的程序的时候必用的。

ecb的安装ubuntu:
sudo apt-get install ecb

安装完后在Emacs中按M-x(Alt+X),输入ecb-activate就可以启动ecb了
第一次运行ecb时,要配置一下它所使用的文件夹
M-x customize-option
ecb-source-path
接下来就是图形化界面的配置了,把常用的代码目录都加进去吧,单击Finish可以关闭,关闭前别忘了保存。

配置完后可能鼠标单击没反应,可修改ecb-primary-secondary-mouse-buttons选项:
M-x customize-option
ecb-primary-secondary-mouse-buttons
选第三个(Primary: mouse-1, secondary: mouse-2)即可

Friday, August 5, 2011

QT Memory Management

转载:红尘弥漫  http://snailsblog.appspot.com/?p=206001
所有继承自QObject的类,如果设置了parent(在构造时,或用setParent函数,或parent的addChild相关信息),那在parent被delete时,这个parent的相关所有child都会自动delete,不用用户手动处理。

在正确的QT开发中,顶级的patent一般是在main函数中,而patent生命周期一般都会比child长,所以正常都不会出错,只要我们编码注意不要写出如下代码:
{
QObject*parent=newQObject(0);
QObject*child=newQObject(parent);
deleteparent;
child->...
}

Qt不建议在一个parent的范围之外持有对childs的指针,按它说的当然不会出野指针的问题了。但是非要在parent外持有child的指针,那么Qt推荐使用QPointer,QPointer相当于一个智能指针,不用智能指针前的代码如下:

如果用了QPointer的代码如下
{
QObject*parent=newQObject(0);
QObject*child=newQObject(parent);
QPointer<QObject>p=child;
deleteparent;
if(p.isNull()){
p->...
}
}

在使用之前判断是否为空,这时就不会再出错段错误了。

Wednesday, August 3, 2011

QT中如何进行DEBUG和使用cout,cin

 

如果想输出DEBUG信息:

 
  1. qDebug() << "Date:" << QDate::currentDate();
  2. qDebug() << "Types:" << QString("String") << QChar('x') << QRect(0, 10, 50, 40);
  3. qDebug() << "Custom coordinate type:" << coordinate;


如果想使用,COUT/IN需要使用QTextStream的重载


Qt代码
  1. #include <QApplication>
  2. #include <QTextStream>
  3. int main(int argc, char *argv[])
  4. {
  5. QApplication app(argc, argv);
  6. QTextStream out(stdout);
  7. out << "is QTextStream out " << endl;
  8. return app.exec();