深入Python摘要

英文版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 正则表达式

  • ^ 匹配字符串的开始。
  • $ 匹配字符串的结尾。
  • /b 匹配一个单词的边界。
  • /d 匹配任意数字。
  • /D 匹配任意非数字字符。
  • x? 匹配一个可选的 x 字符 (换言之,它匹配 1 次或者 0 次 x 字符)。
  • x* 匹配0次或者多次 x 字符。
  • x+ 匹配1次或者多次 x 字符。
  • x{n,m} 匹配 x 字符,至少 n 次,至多 m 次。
  • (a|b|c) 要么匹配 a ,要么匹配 b ,要么匹配 c
  • (x) 一般情况下表示一个记忆组 (remembered group) 。你可以利用 re.search 函数返回对象的 groups() 函数获取它的值。

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模块。

 

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 重要性

单元测试是以测试为核心开发策略的重要组成部分。如果你要写单元测试代码,尽早 (最好是在被测试代码开发之前) 开发并根据代码开发和需求的变化不断更新是很重要的。单元测试不能取代更高层面的功能和系统测试,但在开发的每个阶段都很重要:

  • 代码开发之前,强迫你以有效的方式考虑需求的细节。
  • 代码开发中,防止过度开发。通过了所有测试用例,程序的开发就完成了。
  • 重构代码时,确保新版和旧版功能一致。
  • 维护代码时,当你的代码更改导致别人代码出问题时帮你留住面子。(“但 是先生 ,我检入 (check in) 代码时所有的单元测试都通过了…… ”)
  • 在团队开发时,可以使你有信心,保证自己提交的代码不会破坏其他人的代码,因为你可以 先运行其他人的单元测试代码。(我在“代码风暴”中见过这种事情。一个团队将任务拆分,每个人都根据自己那部分的需求开发单元测试,然后与其他成员共享。 没有人会出太大的偏差而导致代码无法集成。

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的工作过程,可以看下面的代码

 

当我们声明一个生成器gen时,函数并没有被调用执行,直到我们第一次调用next()才使得yield返回函数内部x的值1,随后函数停顿在yield语句上,直到下一次next()调用再返回x的值。如果通过for来访问生成器,可以很方便,下面是一个例子。当然yield可以返回你想返回的任何对象。

使用动态函数以及生成器,可以使你的代码抽象度更高,你可以在使用中根据外部规则动态的生成需要的各种函数,保持代码的高度抽象和简洁。

 

18 性能优化

18.2 Python的性能测试框架

Python内置了时间测试框架,只需要导入timeit模块即可以方便的进行性能测试。首先需要生成一个Timer对象,它需要两个参数,均为字符串,前者为测试的函数后者为需要导入的模块名。注意:被测代码需要与记时代码位于不同模块,并给出显式的导入指令。随后便可以通过此对象进行时间测量。有两个方法timeit()和repeat()

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值