英文版Dive in python可以在下面找到中文翻译http://linuxtoy.org/docs/dip/toc/index.html
3.1 模块
模块的__name__,当模块被import时,其为模块的名字,当模块作为main执行的时候,其为__main__
3.2 dictionary
dictionary中的key-value对可是任何类型的,同一词典中,可以混用匹配。
词典的key是大小写敏感的,并且要求是常量类型。可以使用del dic[key]来删除一个元素。
items()返回一个list,其中的元素为二元的tuple,t[0]为key,t[1]=val
3.3 List
List也支持重载+操作,用于将两个list连接起来,并返回一个List,因此它没有extended执行高效。list也支持+=操作来连接两个list。
list的append()操作将一项元素加入到list的末尾,如果想要连接两个list,应该使用extend而不是append.
*可以作用于list,作为重复器。
list在引用[]中可以接两种slice对象,一种是[start:end:step],一种为[sliece(start,end,step)]操作返回的slice
内置操作range(start,end,step)返回一个list。
3.4 Tuple
Tuple不能向其增加,删除元素,以及返回索引这样的函数,但有in。可以认为Tuple本身是不可变的,因此可以作为dictionary的key。
Tuple和List可以互相显式的进行转换,对内容进行冻结或解冻。tuple可以看作是C中的enum类型。其中元素不可改变,而且是可随机访的。变量按位置得到一个整数值。
变量使用时不需要先声明其类型,但所使用的变量必须之前经过定义。
python支持一次给多个变量赋值,如t=(1,2,3) (x,y,z)=t。
3.5 格式化字符串
与C中sprintf一样的用法类似,print "%s,/t %d" %(str, 10)
当定义一个只包含一个元素的 tuple 时逗号是必须的。如果省略逗号,Python 不会知道 (userCount) 究竟是一个只包含一个元素的 tuple 还是变量 userCount 的值。
t = (1) //type(t) ==> int
t = (1,) //type(t) ==> tuple
3.6 映射list
使用[],通过对lista中第个元素应用一个函数,从而生成另一个list。如[expression for elem in list1]
将一个list的映射交给自己是安全的。
4.5 过滤List
如果在是[ express for elem in list1 if if_express ],以if开头的称之谓过滤表达式。在python中,过滤表达式返回为真时,元素才会加入到映射list中。
3.7 基于字符的list中元素的连接与分割
"delem".join(list1) 将list中的字符按delem符号分割然后连接成一个字符串。
相反的操作可以在字符串上调用split("delem",cnt),它将对一个str,按delem进行分割cnt次,把元素放入list中并返回这个list;
有用的技巧是" " .join(string.split()),它去除string中的多余空格,再使用单个空格将它们格式化连起来。
4.2 函数
python中的函数参数列表可以看作是一个词典,参数可以不按定义的顺序进行传递,但此时需要显式的指定参数名称。
str和type可以接受任何类型的对象,前者返回其str,后者返回其类型。这些内置函数都包含在__builtin__中。
getattr(obj,'name' [,default]) 返回obj上名称为name的属性引用。这个函数可以作用于任何对象,返回方法引用或数据引用。
4.6 逻辑表达式 and/or
使用 and 时,在布尔环境中从左到右演算表达式的值,会一直计算直到返回假,此时返回这个假的对象,否则返回最后一个(真)对象。
0 、'' 、[] 、() 、{} 、None 在布尔环境中为假;其它任何东西都为真。
使用 or 时,在布尔环境中从左到右演算值,就像 and 一样。如果有一个值为真,or 立刻返回该值。否则返回最后一个(假)对象。
and-or 技巧,也就是 bool and a or b 表达式,当 a 在布尔环境中的值为假时,不会像 C 语言表达式 bool ? a : b 那样工作。a为真时,可以像C中的三目表达式。安全的使用方法为 (1 and [a] or [b])[0]
4.7 Lambda表达式
python中只能定义单行函数。但它可以接受多个参数,任何使用lambda函数的地方都可以使用普通函数封闭,而且没有复杂度限制。
5.2 对象导入
模块对象
import module 不会使得module下面的方法可见,如果要使用其下的方法,需要使用module.method来引用。如果要经常使用,可以用from module import method来使method可见。尽量少要from module import *
5.3 类
如果在类中定义了__init__,并且你的类继承了其它类,那么你需要在__init__()中显式的调用基类的__init()函数。__init__()虽然不能称之谓构造函数,但它承担了一个对象在构造后的初始化工作,当你需要一个类的对象实例时,你需要调用类,并传入在__init__()定义的参数。
类的数据成员可以在首次定义时突然加入类中,并可以动态加入和删除。与C++不同的是,在类的内部,我们要引用数据或方法成员时,需要显式的指定self(类似于this指针)。
每个类都有一个内置属性__module__,它用来说明对象所属的模块。
5.6 专用类方法
在类中以__*__形式的一些内置函数,它由类自己定义,并在合适的时候由python的外部函数调用,例如每个类可以定义自己的__str__(),当内置函数str()作用在一个类上时,这个类的__str__()将被调用。这些称之为类型的自我表达能力。
在python中查看两个对象的同一性用is,查看两个对象是否相等用==
5.8 类属性
类的对象由属性__class__标识其所属的类,我们可以通过它模拟C++类中的静态变量。python中没有私有变量,但所有以__开头的变量会被mangle名称,导致在外部不可见。
5.9 私有函数
如果一个 Python 函数,类方法,或属性的名字以两个下划线开始 (但不是结束),它是私有的;其它所有的都是公有的。 Python 没有类方法保护 的概念 (只能用于它们自已的类和子类中)。类方法或者是私有 (只能在它们自已的类中使用) 或者是公有 (任何地方都可使用)。
6.1 异常处理
如果使用一个具有层次的异常处理逻辑,当异常没有发生时,可以使用else来处理层次逻辑。
6.2 文件操作
标准内置函数有open() seek() tell() read() write() close()
6.3 路径与目录操作
在os.path中的函数有split() splitext(),join()等工具
在os中,有操作isfile(), isdir(),chdir(),fchdir(),getcwd(),fdopen(),popen(),dup(),fstat()等
7.1 正则表达式
Python正则表达式HowTo
8 html处理
html的基本知识
8.5 命名空间
locals()返回局部命名空间中的变量,dict形式,但其为复本,修改这个字典不会改变局部命名空间中的变量值。globals()返回全局命名空间中的变量,dict形式,其为引用,修改这个字典将改变全局命名空间中的变量值。
在一个Python程序的任何地方都有几个命名空间,局部,全局,内置。对名称的查找也按上这个顺序进行。
局部命名空间:函数或类的方法中。
全局命名空间:特指当前模块中
内置命名空间:对任何模块都可见的。
8.6 基于字典的字符串格式化
采用如下的形式 dict = {key1:value1, key2:value2, ...} " we can see key1's value is %(key1)s "
8.8 SGMLlib中SGMLParser的工作原理
SGMLParser中定义了如何处理标记语言的方法,用户通过继承此类并定义类似于start_a() end_a()这样的函数,当解析器遇到标记<a>和</a>时会查看用户是否定义了相应的处理函数,如果定义了,则调用用户函数来进行操作。否则则调用unkonw_starttag(),unknown_endtag()来处理,用户可以重载这些函数来定义自己想要操作。
8.9 动态的python
python可以通过字符串,在运行的时候得到相应的属性及类或者实例,对于属性可以通过getattr(),对于命名空间中的类可以直接通过str类型的名字在globals()返回的字典中查到。
9 XML处理
9.2 包的概念
可以认为最基本模块就是.py文件,一个包就是一个目录。包可以嵌套,被嵌套的包或者被包含的模块可以通过 "."来取得。包可以被导入成为一个模块,这是通过包目录下的__init__.py文件中定义的导入名称做到的。包的目录下必须包含__init__.py文件,它可以为空,但必须存在,否则此目录不被识别为包并导入其内部模块。
9.3 处理XML的接口
xmldoc = dom.parse()
root = xmldoc.childNodes[0]
需要注意的是,在根下面的子结点,标签之间有硬回车作为子结点分隔。数据在叶子结点之下,通过childNodes[0].data 取到。
通过这两个接口即可以对简单的XML文件进行遍历。任何结点都有方法toxml()及属性 childNodes。
每个结点可以有属性和文本,通过attributes或data可以进行访问,attributes返回一个字典,里面属性的键值对。分别可以通过keys()和values()获得。
9.4 字符编码
环境中的编码,通过 sys.getdefaultencoding()或sys.setdefaultencoding()来获取或指定。对于每个文件 #-*- coding : UTF-8 -*-
9.5 搜索XML文档
通过getElementsNameByTagName()可以返回一组具有相同标签名的子树。顺序遍历返回的val[i]即可
10 脚本和流
10.1 file-like对象
特指所有支持read(size = none)操作的对象,Python中定义了许多函数可以直接操作file-like对象,而不用用户显式的调用file-like对象的read和close 操作,如xml.minidom.parse()函数。
10.2 输入输出重定向
通过保存及改写sys.stdout,sys.stdin,sys.stderr为其它文件文件对象即可实现输入输出的重定向。为了不用指定一个文件 (例如 binary.xml ),你需要指定“- ”,它会使得你的脚本从标准输入载入脚本,而不是从磁 盘上的特定文件。
10.3 处理命令行参数
可以使用sys.argv以及getopt模块。
import getopt def test_getopt(argv=None): if argv==None: print("error") return opts,args = getopt.getopt(argv,"hp:d:",["help","port","dst"]) print(opts) print(args) for opt,arg in opts: if opt in ('-h','--help'): print("user need help") elif opt in ('-p','--port'): print('port is %s'%arg) elif opt in ('-d','--dst'): print('dst is %s'%arg) else: break str = '-h -p 80 -d 192.168.1.1 "c:/boot.ini"' if __name__ == "__main__": test_getopt(str.split()) test_getopt() #output is followed #[('-h', ''), ('-p', '80'), ('-d', '192.168.1.1')] #['"c:/boot.ini"'] #user need help #port is 80 #dst is 192.168.1.1 #error #
11 处理HTTP
在python 3中,将htmllib删除,相应功能移入urllib中。
http的规范可以参考RFC2616 http1.1的协议规范
12 SOAP
12.1 WSDL
WSDL是一种网络服务描述的规范,它由XML写成,这样一个服务可以被机器自动识别并处理,而不需要程序员去处理由WSDL描述的服务。此外不同企业可以通过UDDI将发布的各种服务整合起来,从而完成更大的工作流。
相关WSDL与UDDI的信息可以参考这里
12.2 SOAP
SOAP基于WSDL中描述的服务,使用HTTP协议在网络不同节点间传递和接收消息,可以完成RPC的功能。这样用户使用WSDL获得网络上服务描述,由机器解析WSDL并得出如何使用服务,使用SOAP将服务调用消息发送给服务描述中给出的服务器。服务器处理收到的XML文档,完成相关的功能,然后采用SOAP将结果传送回来。使高层用户不需要关注服务的具体细节,提高工作效率。
13 单元测试
13.1 重要性
单元测试是以测试为核心开发策略的重要组成部分。如果你要写单元测试代码,尽早 (最好是在被测试代码开发之前) 开发并根据代码开发和需求的变化不断更新是很重要的。单元测试不能取代更高层面的功能和系统测试,但在开发的每个阶段都很重要:
13.4 测试用例的要求
一个测试用例应该做到:
13.5 测试用例的分类
正面测试用例:对于所有有效的输入,必须保证正确的输出
负面测试用例:对于所有无效的输入,必须保证正确的处理,负面测试用例分为:类型,范围
完备性测试: 输入输出的模式是否有效
更多关于测试框架的内容请参见:Python单元测试框架说明
14 测试先行的开发
15 重构
16 函数编程
16.5 数据中心思想编程
使用map,filter这类函数,可以使用程序员不需要去使用for来处理过程的每一步,使程序员只需要关注如何处理数据。
16.6 模块的动态导入
借助于__import__('module'),程序员可以动态的导入以字符串形式给出的模块名称。
17 动态函数
17.7 yield生成器
yield生成器必须在函数内部使用,使用了yield的函数称为generator函数,yield可以使用此generator函数每次调用next()时都返回一个值,直到其返回对象变得不可迭代。为了说明yield的工作过程,可以看下面的代码
def generator(): x=1 while 1: yield x x+=1 gen=generator() for i in range(10): print gen.next()
当我们声明一个生成器gen时,函数并没有被调用执行,直到我们第一次调用next()才使得yield返回函数内部x的值1,随后函数停顿在yield语句上,直到下一次next()调用再返回x的值。如果通过for来访问生成器,可以很方便,下面是一个例子。当然yield可以返回你想返回的任何对象。
def fibonacci(max): a, b = 0, 1 while a < max: yield a a, b = b, a+b for i in fibonacci(1000): print i
使用动态函数以及生成器,可以使你的代码抽象度更高,你可以在使用中根据外部规则动态的生成需要的各种函数,保持代码的高度抽象和简洁。
18 性能优化
18.2 Python的性能测试框架
Python内置了时间测试框架,只需要导入timeit模块即可以方便的进行性能测试。首先需要生成一个Timer对象,它需要两个参数,均为字符串,前者为测试的函数后者为需要导入的模块名。注意:被测代码需要与记时代码位于不同模块,并给出显式的导入指令。随后便可以通过此对象进行时间测量。有两个方法timeit()和repeat()