《Python基础教程》



步长不能为0,但步长可以是负数,即从右到左提取元素,但开始索引必须大于结束索引


2.2.3 序列相加
列表和字符串是无法连接在一起的,尽管它们都是序列。简单来说,两种相同类型的序
列才能进行连接操作。


2.2.4 乘法
用数字乘以一个序列会生成一个新的序列。


None、空列表和初始化
None是一个python的内建值,如果想初始化一个长度为10的列表,可以这样写:
sequence = [None]*10;




2.2.5 成员资格
为了检查一个值是否在序列中,可以使用in运算符。该运算符返回布尔值。
在新版本中in可以检查一个子串是否存在于一个字符串中。


2.2.6 长度、最小值和最大值
内建函数len、min和max非常有用。


2.3 python的“苦力"
列表不同于元组和字符串的地方:列表是可变的mutable。并且列表有很多有用的、专门
的方法。


2.3.1 list函数
因为字符串不能像列表一样被修改,所以有时根据字符串创建列表会很有用。list可以
实现这个操作。list函数适用于所有类型的序列,而不只是字符串。


2.3.2 基本的列表操作
2、删除元素
使用del语句来删除元素。


3、分片赋值
分片赋值语句可以在不需要替换任何原有元素的情况下插入新的元素。
number = [1,5]
number[1:1] = [2, 3, 4]


同样,我们也可以这样来删除元素:
number[1:4] = []


2.3.3 列表方法
1、append
lst = [1,2,3]
lst.append(4) #在列表后面追加元素4


2、count
["to", "be", "or", "not", "to", "be"].count("to")


3、extend
a = [1, 2, 3]
b = [4, 5, 6]
a.extend(b)


4、index


5、insert
numbers = [1, 2, 3, 4, 5]
numbers.insert(3, "four")


6、pop
pop方法会移除列表中的一个元素(默认是最后一个),并且返回该元素的值。
x = [1, 2, 3]
x.pop()


7、remove
remove方法用来移除列表中某个值的第一个匹配项:
x = ["to", "be", "or", "not", "to", "be"]
x.remove("be")


8、reverse
reverse方法将列表中的元素反向存放
x = [1, 2, 3]
x.reverse()


如果需要对一个序列进行反向迭代,那么可以使用reversed函数,这个函数并不返回一
个列表,而是返回一个迭代器iterator对象。使用list函数把返回的对象转换成列表也
是可行的:
x = [1, 2, 3]
list(reversed(x))


9、sort
sort方法用于在原位置对列表进行排序。


获得列表副本的方法:
x = [1, 2, 3, 4, 5]
y = x[:]


简单地把x赋值给y是没用的,因为这样做就让x和y都指向同一个列表了。


sorted函数与sorted不同,它会返回一个已排序列表的副本。sorted可以用于任何可迭
代的对象。x.sort()返回None,而sorted(x)返回排序后的x的一个副本


10 高级排序
可以对sort通过compare(x, y)的形式自定义比较函数。内建函数cmp提供了比较函数的
默认实现方式。


sort方法有另外两个可选的参数--key和reverse。


cmp,key,reverse参数都可以用于sorted函数,在多数情况下,为cmp或key提供自定义
函数是非常有用的。


2.4 元组:不可变序列
元组与列表一样,也是一种序列,唯一的不同是元组不能修改。字符串也不能修改。
元组通过圆括号括起来的:(1,2,3)
一个值的元组:(42.) 必须加一个逗号,即使只有一个值。元组没有像列表一样的方法。


2.4.1 tuple函数
tuple函数的功能与list函数基本上是一样的:以一个序列作为参数,并把它转换为元组。
如果参数是元组,就会被原样返回:
tuple([1, 2, 3])


2.4.2 基本元组操作
元组除了创建元组和访问元组元素之外,也没有太多其他操作。
元组的分片还是元组,就像列表的分片还是列表一样。
一、元组可以在映射和集合的成员中当作键使用,而列表则不行。
二、元组作为很多内建函数和方法的返回值存在,也就是说你必须对元组进行处理。只
要不尝试修改元组。那么,“处理”元组在绝大多数情况下就是把它们当作列表来进行
操作(除非需要使用一些元组没有的方法,例如index和count)。




第3章 使用字符串
3.1 基本字符串操作
所有标准的序列操作(索引、分片、乘法、判断成员资格、求长度、取最小值和最大值)
对字符串同样适用。但是,请记住,字符串都是不可变的。


3.2 字符串格式化:精简版
在%的左侧放置一个字符串(格式化字符串),而右侧则放置希望格式化的值。可以使用
一个值,如一个字符串或者数字,也可以使用多个值的元素或者下一章将会讨论的字典
(如果希望格式化多个的话)。一般情况下使用元组:
format = "hello, %s, %s enough for ya?"
values = ("world", "hot")
print format % values


注意,如果使用列表或者其他序列代替元组,那么序列就会被解释为一个值。只有元组
和字典可以格式化一个以上的值。


模板字符串
from string import Template 
s = Template("$, glorious $x!")
s.substitute(x = "slurm")
"slurm, glorious slurm!"


3.3 字符串格式化:完整版
格式化操作符的右操作数可以是任何东西,如果是元组或者映射类型(如字典),那么
字符串格式化将会有所不同。
如果右操作数是元组的话,则其中的每一个元素都会被单独格式化,每个值都需要一个
对应的转换说明符。


基本的转换说明符包括以下部分。注意,这些项的顺序是至关重要的:
一、%字符:标记转换说明符的开始。
二、转换标志(可选):-表示左对齐,+表示在转换值之前要加上正负号;" "表示在正数
之前保留空格;0表示转换值若位数不够则用0填充。
三、最小字段宽度(可选):如果是*,则宽度会从值元组中读出。
四、点.后跟精度值(可选):如果转换的是字符串,那么该数字就表示最大字段宽度。
如果是*,那么精度将会从元组中读出。
五、转换类型:


3.3.1 简单转换


3.3.2 字段宽度和精度
“%10.2f" % pi #字段宽10, 精度2
可以使用*作为字段宽度或者精度或者两者都使用*,此时数值会从元组参数中读出:
"%.*s" % (5, "Guido van Rossum")


3.3.3 符号、对齐和0填充
-减号、左对齐。""空白、正数前加上空格。+不管是正数还是负数都标出符号


3.4 字符串方法
string.digits:包含0~9的字符串
string.letters:包含所有字母,大写或小写的字符串
string.lowercase:包含所有小写字母的字符串
string.printable:包含所有可打印字符的字符串
string.punctuation:包含所有标点的字符串
string.uppercase:包含所有大写字母的字符串


3.4.1 find可以在一个较长的字符串中查找子字符串。它返回子串所有位置最左端的索
引。如果没有找到则返回-1。
find还可以接受可选的起始点和结束点参数:
subject = "Get rich now"
subject.find("rich", 3, 9) #提供起始点和结束点,起始和终止是左闭右开区间


3.4.2 join
它是split的逆方法,用来在队列是添加元素。


3.4.3 lower
lower方法返回字符串的小写字母版。
"Trondheim Hammer Dance".lower()


islower、capitalize、swapcase、title、istitle、upper、isupper。


和lower方法相关的是title方法,它会将字符串转换为标题。
可以再看一个string模块的capwords函数


3.4.4 replace
replace方法返回某字符串的所有匹配项均被替换之后得到的字符串
"This is a test".replace("is", "eez")


3.4.5 split
它是join的逆方法,用来将字符串分割成序列。
注意,如果不提供任何分割符,程序会把所有空格作为分隔符(空格、制表、换行等)。
"Using the default".split()


rsplit、splitlines。


3.4.6 strip
strip方法返回去除两侧(不包括内部)空格的字符串:
"  internal whitespace is kept  ".strip()
也可以指定需要去除的字符,将字们列为参数即可。
"***SPAM * for * everyone!!! ***".strip(" *!")
这个方法只会去除两侧的字符,所以字符串中的星号没有被去掉。 
lstrip、rstrip。


3.4.7 translate
translate方法和replace方法一样,可以替换字符串中的某些部分,但是和前者不同的
translate方法只处理单个字符。它的优势在于可以同时进行多个替换,有些时候比
replace效率高得多。


我们可以用它来替换换行符或者其他因平台而异的特殊字符。


让我们先来看一个简单的例子:
假设需要将纯正的英文文本转换为带有德国口音的版本,为此,需要把字符c替换为k,
把s替换为z。
在使用translate转换之前,需要先完成一张转换表。转换表中是以某字符替换某字符的
对应关系。因为这个表有多达256个项目,我们还是不要自己写了,使用string模块里
面的maketrans函数就行。


maketrans函数接受两个参数:两个等长的字符串,表示第一个字符串中的每个字符都用
第二个字符串中相同位置的字符替换。
from string import maketrans
table = maketrans("cs", "kz")
转换表是包含替换ASCII字符串集中256个字符的替换字母的字符串。


创建这个表之后,可以将它用作translate方法的参数,进行字符串的转换。
"this is an incredible test".translate(table)
translate的第二个参数是可选的,这个参数是用来指定需要删除的字符。


3.5 小结
字符串格式化:%
字符串方法:split, join, replace, translate, lower, upper, find, title, 
istitle, capitalize。


string.capwords(s[.sep]) 使用split函数分割字符串s,以sep为分隔符,使用capitalize
函数将分割得到的各单词首字母大写,并且使用join函数以sep为分隔符将各单词连接
起来


string.maketrans(from, to) 创建用于转换的转换表


列表、字符串和字典是python中最重要的3种数据类型。


字典如何支持索引以及其他方式的键,比如字符串和元组。




第4章 字典:当索引不好用时
字典通过名字引用值的数据结构。这种结构类型称为映射mappint。字典是python中唯
一的内建的映射类型。字典中的值并没有特殊的顺序,但是都存储在一个特定的键里,
键可以是数字、字符串基至是元组。


4.1 字典的使用
某些情况下,字典比列表更加适用,比如:
表征游戏棋盘的状态,每个键都是由坐标值组成的元组。
存储文件修改次数,用文件字作为键。
数字电话/地址簿


教训就是:电话号码,以及其他可能以0开头的数字,应该表示为数字字符串,而不是
整数。


4.2 创建和使用字典
字典可以通过下面的方式创建:
phonebook = {"Alice":"2341", "Beth":"4332", "Ceil":"3244"}
字典由多个键及与其对应的值构成的对组成,我们也把键/值对称为项。


注意,字典中的键是唯一的,其他类型的映射也是如此,而值并不唯一。


4.2.1 dict函数
可以用dict函数,通过其他映射(比如其他字典)或者(键、值)这样的序列对建立字典。
items = [('name', 'Gumby'), ('age', 42)]
d = dict(items)
dict函数也可以通过关键字参数来创建字典,如下:
d = dict(name = 'Gumby', age = 42)
相当于
{'age':42, 'name':"Gumby'}


4.2.2 基本字典操作
字典的基本行为在很多方面与序列类似:
len(d)返回d中项(键-值对)的数量
d[k]返回关联到键k上的值
d[k]=v将值v关联到键k上。
del d[k]删除键为k的项
k in d检查d中是否含有键为k的项。


4.2.3 字典的格式化字符串
这类字符串格式化在模板系统中非常有用:
template='''<html>
<head><title>%(title)s</title><head>
<body>
<h1>%(title)s</h1>
<p>%(text)s</p>
</body>'''


data = {'title':'My Home Page', 'text':'Welcome to my home pate!'}
print template % data


4.2.4 字典方法
1、clear
清除字典中所有的项,这是个原地操作,类似于list.sort,所以无返回值,或者说
返回None。


2、copy
返回一个具有相同键值对的新字典。这个方法实现的是浅复制shallow copy。
可以使用deepcopy来进行深复制


3、fromkeys
fromkeys方法使用给定的键建立新的字典,每个键默认对应的值为None。
也可以直接在所有字典的类型dict上面调用方法。
dict.fromkeys(['name', 'age'], 'unknown')


4、get
当使用get访问一个不存在的键时,没有异常,而是得到了None值。还可以自定义默认
值。


5、has_key
表达式d.has_key(k)相当于表达式k in d。


6、items和iteritems
将字典以列表方式返回,但是项在返回时并没有特殊的顺序。


7、keys和iterkeys
keys方法将字典中的键以列表形式返回,而iterkeys则返回针对键的迭代器。


8、pop


9、popitem
popitem弹出随机的项,字典中没有与append等价的方法。因为字典是无序的,类似于
append的方法是没有任何意义的。


10、setdefault


11、update
可以利用一个字典项更新另外一个字典。


12、values和itervalues
values方法以列表的形式返回字典中的值(itervalues返回值的迭代器)。与返回键的列
表不同的是,返回值的列表中可以包含重复的元素:


映射可以使用任何不可变对象标识元素。最常用的类型是字符串和元组。python唯一内建
的映射类型是字典。




第5章 条件、循环和其他语句
列表推导式list comprehension如何扮演循环和条件语句的角色---尽管它本身是表达式。
最后介绍pass、del和exec语句的用法。


5.1 print和import的更多信息
5.1.1 使用逗号输出
print可以打印多个表达式,只要将它们用逗号隔开就好。并且每个参数之间都要插入一
个空格符。


name = "Gumby"
salutation = "Mr"
greeting = "Hello."
print greeting + ".", salutation, name


5.1.2 把某件事作为另一个件事导入
也可以为函数提供别名:
from math import sqrt as foobar
foobar(4)


有些模块,如os.path是分层次安排的(一个模块在另一个模块的内部)。


5.2 赋值魔法
5.2.1 序列解包
对变量和数据结构成员的(比如列表中的位置和分片以及字典中的槽)赋值。


>>values = 1, 2, 3
>>values
(1, 2, 3)
>>x, y, z = values
>>x
1


当函数或者方法返回元组(或者其他序列或可迭代对象)时,这个特性尤其有用。
假设需要获取(和删除)字典中任意的键-值对,可以使用popitem方法,这个方法将
键-值作为元组返回。那么这个元组就可以直接赋值到两个变量中:
>>scoundrel = {"name":"Robin", "girlfriend":"Marion"}
>>key, value = scoundrel.popitem()
>>key
"girlfriend"
>>value
"Marion"


所解包的序列中的元素数量必须和放置在赋值符号=左边的变量数量完全一致。否则
python会在赋值时引发异常。


5.2.2 链式赋值
chained assignment


5.2.3 增量赋值
如+=, -=, *=, /= ,%= 等叫增量赋值


5.3 语句块:缩排的乐趣
很多语言使用特殊单词或者字符比如begin或{来表示一个语句块的开始,用另外的单词
或者字符比如end或者}表示语句块的结束。在python中,冒号:用来标识语句块的开始,
块中的每一个语句都是缩进的(缩进量相同)。当回退到和已经闭合的块一样的缩进
量时,就表示当前块已经结束了。


5.4 条件和条件语句
5.4.1 这就是布尔变量的作用
因为所有值都可以用作布尔值,所以几乎不需要对它们进行显式转换。


5.4.2 条件执行和if语句


5.4.3 else子句


5.4.4 elif 子句


5.4.5 嵌套的if语句


5.4.6 更复杂的条件
如果你偶然遇见了x<>y这样的表达式,它的意思其实就是x!=y。应该尽量避免这样使用。


比较对象的时候可以使用第2章中介绍的内建的cmp函数。


is:同一性运算符
is运算符是判定同一性而不是相等性。


使用==运算符来判定两个对象是否相等,使用is判定两者是否等同(同一个对象)。
避免将is运算符用来比较类似数值和字符串这类不可变值。


4. in:成员资格运算符
in运算符可以像其他比较运算符一样在条件语句中使用。


5、字符串和序列比较
字符串可以按照字母顺序排列进行比较。
实际上,字符是按照本身的顺序值排列的。一个字母的顺序值可以用ord函数查到,ord
函数与chr函数功能相反。如果要忽略大小写字每的区别,可以使用字符串方法upper和
lower。


序列可以用同样的方式进行比较,不过比较的不是字符而是元素的其他类型。
>>[2, [1, 4]] < [2, [1, 5]]
true


6、布尔运算符
and运算符就是所谓的布尔运算符。它连接两个布尔值,并且在两者都为真时返回真,否
则返回假。与它同类的还有两个运算符,or和not。
python中的布尔运算符也有短路的性质。


5.4.7 断言
if语句有个非常有用的“近亲”.即assert。
>>age = -1
>>assert 0 < age < 100, "The age must be realistic"


5.5 循环
5.5.1 while循环
x = 1
while x <= 100:
print x
x += 1


5.5.2 for循环
words = ['this', 'is', 'an', 'ex', 'parrot']
for word in words:
print word
因为迭代某范围的数字是很常见的,所以有个内建的范围函数供使用:
>>range(0, 4)
[0,1,2,3]
range函数的工作方式类似于分片。如果希望下限为0,可以只提供上限。


下面的程序会打印1-100的数字
for number is range(1, 101):
print number
如果能使用for循环,就尽量不用while循环。


5.5.3 循环遍历字典元素
d = {"x":1, "y":2, "z":3}
for key in d:
print key, "corresponds to ", d[key]


如果只需要字典的值,可以使用d.values替代d.keys。d.items方法会将键-值对作为元组
返回,for循环的一大好处就是可以循环中使用序列解包:
for key, value in d.items():
print key, "corresponds to ", value


5.5.4 一些迭代工具
1、并行迭代
程序可以同时迭代两个序列。
names = ["anne", "beth", "george", "damon"]
ages = [12, 45, 32, 102]
如果想要打印名字和对应的年龄,可以像下面这样做:
for i in range(len(names)):
print names[i], "is" ages[i], "years old"


而内建的zip函数可以用来进行并行迭代,可以把两个序列“压缩”在一起,然后返回一
个元组的列表:
>>zip(names, ages)
[("anne", 1), ("beth", 45), ("george", 32), ("damon", 102)]
现在我们可以在循环中解包元组:
for name, age in zip(names, ages):
print name, "is", age, "years old"


zip可以应付不等长的序列:当最短的序列用完的时候就会停止。


>>zip(range(3), xrange(100000000))
[(0,0), (1,1), (2,2)]
在上面中,不推荐用range替代xrange,range会计算所有的数字,而xrange只计算前5个。


2、 编号迭代
使用内建的enumerate函数
这个函数可以在提供索引的地方迭代索引--值对
for index, string in enumerate(strings):
if "xxx" in string:
strings[index] = "[censored]"


3、翻转和排序迭代
看看另外两个有用的函数:reversed和sorted:它们同列表的reverse和sort(sorted和
sort使用同样的参数)方法类似,但作用于任何序列或可迭代对象上,不是原地修改
对象,而是返回翻转或排序后的版本。


5.5.5 跳出循环
1、break
例如,下面找到100以内的最大平方数:
from math import sqrt
for n in range(99, 0, -1):
root = sqrt(n)
if (root == int(root)):
print n
break




2、continue


5.6 列表推导式--轻量级循环
[x*x for x in range(4) if x % 3 == 0]
[0, 9]


也可以增加更多for语句的部分:
[(x, y) for x int range(3) for y in range(3)]


5.7 三人行
看另外3个语句:pass, del和exec。
5.7.1 pass什么都没有发生
5.7.2 使得del删除对象的名字。
5.7.3 使用exec和eval执行和求值字符串




第6章 抽象
6.2 抽象和结构
6.3 创建函数
使用del定义函数


6.4 记录函数
如果想要给函数写上文档,可以加入注释(以#开头)。另外一个方式就是直接写上字符
串。
如果在函数的开头写下字符串,它就会作为函数的一部分进行存储,这称为文档字符串。
例如:
def square(x):
"Calculates the square of the number x"
return x*x


函数可以返回一个以上的值,元组中返回即可。


内建的help函数是非常有用的。


6.3.2 并非真正函数的函数
return;  返回的是为None


6.4 参数魔法
字符串(以及数字和元组)是不可变的,即无法被修改(也就是说只能用新的值覆盖)。


6.4.3 关键字参数和默认值
目前为止我们所使用的参数都叫做位置参数,因为它们的位置很重要。
这类使用参数名提供的参数叫做关键字参数。


位置参数和关键字参数是可以联合使用的。把位置参数放置在前面就可以了。


使用拼接splicing操作符传递参数很有用,因为这样一来就不用关心参数的个数之类
的问题。
def foo(x, y, z, m = 0, n =  0):
print x, y, z, m, n
def call_foo(*args, **kwds)
print "calling foo!"
foo(*args, **kwds)
在调用超类的构造函数时这个方法尤其有用。


6.5 作用域
可以使用globals函数获取全局变量值,该函数的近亲是vars,它可以返回全局变量的
字典locals返回局部变量的字典。


如果在函数内部将值赋予一个变量,它会自动成为局部变量,除非告知python将其声明
为全局变量。


python的函数是可以嵌套的。


python在应对这类“函数式编程”方面有一些有用的函数:map、filter和reduce函数。
python3.0中这些都被移至functools模块中。map和filter函数在目前版本的python中
并不是特别有用,并且可以使用列表推导式代替。可以使用map函数将序列中的元素全
部传递给一个函数:
>>map(str, range(10))
filter函数可以基于一个返回布尔值的函数对元素进行过滤。
>>def func(x)
return x.isalnum()
>>seq = ["foo", "x41"]
>>filter(func, seq)
本例中,使用列表推导式可以不用专门定义一个函数:
>>[x for x in seq if x.isalnum()]
事实上,还有一个叫做lambda表达式的特性,可以创建短小的函数
>>filter(lambda x: x.isalnum(), seq)


reduce函数一般来说不能轻松被列表推导式替代。




第7章 更加抽象
前面介绍了python主要的内建对象类型,数字,字符串,列表,元组和字典。以及内
建函数和标准库的用法,还有自定义函数的方式。
本章会介绍创建对象,以及多态、封装、方法、特性、超类以及继承概念。


标准库random中包含choice函数,可以从序列中随机选出元素。给变量赋值:
>>from random import choice
>>x = choice(["Hello, world!", [1, 2, "3", "e"]])


7.1.2 封装
7.2.3 特性、函数和方法
为了让方法或者特性变为私有,只要在它的名字前面加上双下划线即可。


所有以双下划线开始的名字都被“翻译”成前面加上单下划线和类名的形式。


7.2.3 指定超类
将其他类名写在class语句后的圆括号内可以指定超类:
7.2.6 调查继承
如果想要查看一个类是否是另一个的子类,可以使用内建的issubclass函数:
如果想要知道已知类的基类,可以直接使用它的特殊特性__bases__:
同样,还能使用isinstance方法检查一个对象是否是一个类的实例。




第8章 异常
8.2.1 raise语句
为了引发异常,可以使用一个类(应该是Exception的子类)或者实例参数调用raise语句
使用类时,程序会自动创建实例。


8.3 捕获异常
在python3.0中,except子句会被写作except(ZeroDivisionError, TypeError) as e.


8.9 最后
最后是Finally子句。它可以用来在可能的异常后进行清理。它和try子句联合使用。


第9章 魔法方法、属性和迭代器
在Python中,有的名称会在前面和后面都加上两个下划线。如__future__,这种拼写
表示名字有特殊含义。在python中,由这些名字组成的集合所包含的方法称为魔法(或
称特殊)方法。


属性(在以前版本的python中通过魔法方法来处理,现在则通过property函数)和迭代
器(使用魔法方法__iter__来允许迭代器在for循环中使用)。


在python3.0中没有旧式的类,也不需要显示地子类化object或者将元类设置为type。
所有的类都会隐式地成为object的子类--如果没有明确超类的话,就会直接子类化,
否则会间接子类化。


9.2 构造方法
python中的构造方法是__init__,在python所有的魔法方法中,__init__是使用最多的
一个。python中另一个魔法方法叫做__del__,也就是析构方法。它在对象就要被垃圾
回收之前调用,但发生调用的具体时间是不可知的,所以建议读者尽力避免使用
__del__函数。


9.5.1 property函数
property函数可以用0、1、2、3或者4个参数来调用。如果没有参数,产生的属性即不
可读,也不可写。第3个参数(可选)是一个用于删除特性的方法,它不要参数。第
4个参数(可选)是一个文档字符串。property的4个参数分别叫做fget、fset、fdel和
doc__。
在新式类中应该使用property函数而不是访问器方法。


9。5.2 静态方法和类成员方法
静态方法和类成员方法分别在创建时分别被装入Staticmethod类型和Classmethod类型
的对象中。静态方法的定义没有self参数,且能够被类本身直接调用。类方法在定义时
需要名为cls的类似于self的参数。类成员方法可以直接用类的具体对象调用。但cls
参数是自动被绑定到类的。
__metaclass__ = type
class MyClass:
def smeth():
print "this is a static method"
smeth = staticmethod(smeth)
def cmeth():
print "This is a class method of" .cls
cmeth = classmethod(cmeth)
为这样的包装方法引入了一个叫做装饰器decorator的新语法,它既能够用于方法也能用
于函数。使用@操作符,在方法(或函数)的上方将装饰器列出。
__metaclass__ = type
class MyClass:
@staticmethod
def smeth():
print "This is a static method"
@classmethod
def cmeth(cls):
print "This is a class method of", .cls


9.6 迭代器
__iter__,这个方法是迭代器规则iterator protocol的基础。
__iter__方法返回一个迭代器iterator,所谓的迭代器就是具有next方法,这个方法在
调用时不需要任何参数。
在新的规则中,迭代器对象应该实现__next__方法,而不是next。而新的内建函数next
可以用于访问这个方法,换句话说,next(it)等同于之前版本的it.next()。


一个实现在__iter__方法的对象是可迭代器的,一个实现了next方法的对象则是迭代器。
内建函数iter可以从可迭代的对象中获得迭代器。
>>it = iter([1,2,3])
>>it.next()
1
>>it.next()
2


9.6.2 从迭代器得到序列
除了在迭代器和可迭代对象上进行迭代外,还能把它们转换为序列。
>>it = TestIterator()
>>list(it)
[1,2,3,4]


9.7 生成器
也叫简单生成器。它和迭代器可能是近几年来引入的最强大的两个特性。
生成器是一种用普通的函数语法定义的迭代器。


9.7.1 创建生成器
创建一个生成器就像创建一个函数一样简单。
下面是一个展开嵌套列表的函数:
def flatten(nested):
for sublist in nested:
for element in sublist:
yield element
任何包含yield语句的函数称为生成器。它不像return那样返回值,而是每次产生多个
值。每次产生一个值(使用yield语句),函数就会被冻结:即函数停在那点等待被
激活。函数被激活后就从停止的那点开始执行。


9.7.3 通用生成器
生成器是一个包含yield关键字的函数。当它被调用时,在函数体中的代码不会被执行,
而会返回一个迭代器。每次请求一个值,就会执行生成器中的代码,直到遇到一个
yield或者return语句。yield语句意味着应该生成一个值。return语句意味着生成器
要停止执行(不再生成任何东西,return语句只有在一个生成器中使用才能进行无参数
调用。


即,生成器是由两部分组成:生成器的函数和生成器的迭代器。生成器的函数是用def
语句定义的,包含yield的部分,生成器的迭代器是这个函数返回的部分。


9.7.4 生成器方法
外部作用域访问生成器的send方法,就像访问next方法一样,只不过前者使用一个参数
(要发送“消息”--任意对象)
在内部则挂起生成器,yield现在作为表达式而不是语句使用,换句话说,当生成器重
新运行的时候,yield方法返回一个值,也就是外部通过send方法发送的值。如果next
方法被使用,那么yield方法返回None。




第10章 充电时刻
2.在模块中增加测试代码
在主程序中,变量__name__的值是"__main__",而在导入的模块中,这个值被设定为
模块的名字。


使用条件测试代码的模块
# hello4.py
def hello():
print "Hello. world!"
 
def test():
hello()
if __name__ == '__main__':test()


将测试代码放入独立的test函数会更灵活。如果需要编写更完整的测试代码,将其放置
在单独的程序中会更好。


10.1.3 让你的模块可用
前面我们看到了sys.path,其中包含了(字符串组成的)一个目录列表,解释器在该
列表中查找模
1、将你的模块放置在正确的位置。
搜索路径的目录的列表可以在sys模块中的path变量中找到:
>>import sys.pprint
>>pprint.pprint(sys.path)
如果你的数据结构过大,不能在一行打印完,可以使用pprint模块中的pprint函数代替
普通的print语句,pprint是个相当好的打印函数,能够提供更加智能的打印输出。


虽然上面打印出来的目录都可以使用,但site-packages目录是最佳选择,因为它就是
用来做这些事情的。


2、告诉编译器去哪里找
环境变量是操作系统的一部分。基本上,它相当于Python变量,不过是在Python解释器
外设置的。


在UNIX和Mac OS X中,你可以在一些每次登录都要执行的shell文件内设置环境变量。如
果你使用类似bash的shell文件,那么要设置的就是.bashrc。


3.命名模块
包含模块代码的文件的名字要和模块名一样,再加上.py扩展名。在windows系统中,你
也可以使用.pyw扩展名。


10.1.4 包
当模块存储在文件中时(扩展名.py),包就是模块所在的目录。为了让python将其作
为包对待,它必须包含一个命名为__init__py的文件(模块)。


10.2 探究模块
10.2.1 模块中有什么
1.使用dir
查看模块包含的内容可以使用dir函数,它会将对象(以及模块的所有函数、类、变
量等)的所有特性列出。如想打印dir(copy)的内容,你会看到有一些名字以下划线开始
---暗示它们并不是为在模块外部使用而准备的。所以让我们用列表推导式过滤掉它们:
>>[n for n in dir(copy) if not n.startswitch('__')]


2、__all__变量
__all__变量定义了模块的公有接口public interface。如果没有设定__all__,用
import*语句默认将会输出模块中所有不以下划线开头的全局名称。


10.2.2 用help获取帮助
>>help(copy.copy)
__doc__,你还记得前面讲到过的文档字符串吗,它是写在函数开头并且简述函数功能
的字符串。这个字符串可以通过函数的__doc__特性引用。类也可以有文档字符串,写
在类开头。


使用help与直接检查文档字符串相比,它的好外在于会获得更多信息,比如函数签名(
也就是所带的参数)。


10.2.3 文档
通过模块的__file__属性我们可以看到模块的路径。


注意,一些模块并不包含可以阅读的python源代码,它们可能已经融入到解释器内了
(比如sys模块),或者可能是使用C程序语言写成的。


10.3 标准库: 一些最爱
10.3.1 sys
sys这个模块让你能够访问与python解释器联系紧密的变量和函数。
argv exit([arg]) modules path platform stdin
stdout stderr


10.3.2 os
os模块为你提供了访问多个操作系统服务的功能。另外,os和它的子模块os.path还包括
一些用于检查、构造、删除目录和文件的函数,以及一些处理路径的函数(例如,
os.path.split和os.path.join让你在大部分情况下可以忽略os.pathsep)。
函数/变量 描述
environ 对环境变量进行映射
system(command) 在子shell中执行操作系统命令
sep 路径中的分隔符
pathsep 分隔路径的分隔符
linesep 行分隔符('\n','\r',or '\r\n'
urandom(n) 返回n字节的加密强随机数据


当前版本的python中,包括subprocess模块,它包括了os.system、execv和popen函数
的功能。
os.sep模块变量是用于中径中的分隔符。UNIX使用的标准分隔符是"/",windows是"\\"
而Mac OS中是":"。有些平台上,os.altsep包含可选的路径他隔符,比如windows中的
"/"。


pathsep用于分割路径名:UNIX使用":",windows使用";",Mac OS使用"::"。


os.linesep用于文本的字符串分隔符。UNIX中为一个换行符\n,windows为\r\n,Mac OS
中使用\r。


在命令提示符中,对于有空格路径的命令,需要使用双引号将命令括起来。


10.3.3 fileinput
fileinput模块中的重要的函数:
input([files[,inplace[.backup]]) 便于遍历多个输出流中的行
filename() 返回当前文件的名称
lineno() 返回当前(累计)的行数
filelineno() 返回当前文件的行数
isfirstline() 检查当前行是否是文件的第一行
isstdin() 检查最后一行是否来自sys.stdin
nextfile() 关闭当前文件,移动到下一个文件
close() 关闭序列


10.3.4 集合、堆和双端队列
python支持有些相对通用的数据类型,例如字典(或者说散列表)、列表(或者说动态
数组)是语言必不可少的一部分。


1.集合
Set类位于sets模块中。在python2.3中,集合通过set类型的实现成为了语言的一部分,
这意味着不需要导入sets模块了。直接创建集合即可:
>>set(range(10))
set([0,1,2,3,4,5,6,7,8,9])
集合是由序列(或者其他可迭代的对象)构建的。它们主要用于检查成员资格,因此
副本是被忽略的。
和字典一样,集合元素的顺序是随意的。


如要找出两个集合的并集,可以使用其中一个集合的union方法或者使用按位与OR运算
符"|":
>>a = set([1,2,3])
>>b = set([2,3,4])
>>a.union(b)
set([1,2,3,4])
>>a|b
set([1,2,3,4])


集合是可变的,所以不能用做字典的键。另外一个问题就是集合本身只能包含不可变
(可散列的)值,所以也就不能包含其他集合。在实际中,集合的集合是很常见的,所
以这就是个问题的。幸好还有个frozenset类型,用于代表不可变(可散列)的集合。
>>a = set()
>>b = set()
>>a.add(b)
error
>>a.add(frozenset(b))
ok
frozenset构造函数创建给定集合的副本,不管是将集合作为其他集合成员还是字典的
键,frozenset都很有用。


2、堆
堆heap,它是优先队列的一种。


事实上,python中并没有独立的堆类型---只有一个包含一些堆操作函数的模块,这个
模块叫做heapq(q是queue的缩写,即队列),包括6个函数。前4个直接和堆操作相关,
你必须将列表作为堆对象本身。
函数 描述
heappush(heap, x) 将x入堆
heapup(heap) 将堆中最小的元素弹出
heapify(heap) 将heap属性强制应用到任意一个列表 
heapreplace(heap, x) 将堆中最小的元素弹出,同时将x入堆
nlargest(n, iter) 返回iter中第n大的元素
nsmallest(n, iter) 返回iter中第n小的元素


堆元素的顺序并不像看起来那么随意。它们虽然不是严格排序的,但是也有规则的:位
于i位置上的元素总比i/2位置处的元素大(反过来说就是i位置外的元素总比2*i以及
2*i+1位置处的元素小)。这是底层堆算法的基础,而这个特性称为堆属性(heap propery)。
heappop函数弹出最小的元素---一般来说都是在索引0处的元素,并且会确保乘余元素中
最小的那个占据这个位置(保持刚才提到的堆属性)。


heapify函数使用任意列表作为参数,并且通过尽可能少的移位操作,将其转换为合法
的堆。如果没有用heappush建立堆,那么在使用heappush和heappop前应该使用这个函数。


3、双端队列
双端队列(double-ended queue,或称deque)在需要按照元素增加的顺序来移除元素时
非常有用。python增加了collections模块,它包括deque类型。


python2.5中的collections模块只包括deque类型和defaultdict类型。




10.3.5 time
(2008,1,21,12,2,56,0,21,0)
表示2008年1月21日12时2分56秒,星期一,并且是当年的第21天(无夏令时)。


tiem.asctime()
将当前时间格式化为字符串。


函数 描述
asctime([tuple]) 将时间元组转换为字符串
localtime([secs]) 将秒数转换是日期元组,以本地时间为准
mktime(tuple) 将时间元组转换为本地时间 
sleep(secs) 休眠(不做任何事情)secs秒
strptime(string[,format]) 将字符串解析为时间元组
time() 当前时间(新纪元开始后的秒数,以UTC为准)


如果不需要使用当前时间,还可以提供一个日期元组(比如通过localtime创建的)。
为了实现更精细化的格式化,你可以使用strftime函数,标准文档对此有相应的介绍。


此外,python还提供了两个和时间密切相关的模块:datetime(支持时期和时间的算法)
和timeit(帮助开发人员对代码段的执行时间进行计时)。


10.3.6 random
它产生的都是伪随机数,如果真的需要随机性,应该使用os模块的urandom函数。random
模块内的SystemRandom类是也基于同种能功。可以让数据接近真正的随机性。


10.3.7 shelve
shelve中open函数,在调用它的时候(使用文件名作为参数),它会返回一个shelf对象,
你可以用它来存储内容。


10.3.8 re
re模块包含对正则表达式的支持。
通配符


字符串的开始和结尾
re模块的内容
模式对象本身也有查找/匹配的函数,就像方法一样,所以re.search(pat, string)
(pat是用字符串表示的正则表达式),等价于pat.search(string)(pat是用compile创建
的模式对象)。经过compile转换的正则表达式对象也能用于普通的re函数。


re.escape是一个很实用的函数,


3.匹配对象和组
对于re模块中那些能够对字符串进行模式匹配的函数而言,当能找到匹配项的时候,它
们都会返回MatchObject对象。这些对象包括匹配模式的子字符串的信息。它们还包含
了哪个模式匹配了子字符串哪部分的信息---这些部分叫做组group。


组就放置在圆括号内的子模式。组的序号取决于它左侧的括号数,组0就是整个模式。

r'www\.(.+)\.com$'
组0包含整个字符串,而组1则包含位于'www.'和'.com'之间的所有内容。


re匹配对象的一些方法:
方法 描述
group([group1, ...]) 获取给定子模式(组)的匹配项
start([group]) 返回给定组的匹配项的开始位置
end([group]) 返回给定组的匹配项的结束位置(和分片
一样,不包括组的结束位置)
span([group]) 返回一个组的开始和结束位置


4.作为替换的组号和函数


重复运算符默认是贪婪dreedy的。


10.3.9 其他有趣的标准模块
functools:让你能够通过部分参数来使用某个函数(部分求值),稍后再为剩下的参数
提供数值。在python3.0中,filter和reduce包含在该模块中。
difflib:你可以计算两个序列的相似程序。
hashlib:你可以通过字符串计算小“签名”(数字)。该模块可以应用于大文件文件,
同时在加密和安全性方面有很多用途,另见md5和sha模块。


csv:CSV是逗号分隔值(comma separated values)的简写。


timeit、profile、和trace:timeit模块可以衡量代码片段运行时间。profile模块(和
伴随模块pstats)可用于代码片段效率的全面分析。trace模块(和程序)可以提供总
的分析(也就是代码哪部分执行了,哪部分没有执行)。
datetime:
itertools:它有很多工具用来创建和联合迭代器或者其他可迭代对象。
logging:这个模块提供了一组标准的工具,以便让开发人员管理一个或多个核心的日志
文件,同时还对日志信息提供了多层次的优先级。


getopt和optparse:


cmd:




第11章 文件和素材
11.1 打开文件
open函数用来打开文件。语法如下
open(name[,mode[,buffering]])


11.1.1 文件模式
如果open函数只带一个文件名参数,那么我们可以获得能读取内容的文件对象。如果要
向文件内写入内容,则必须提供一个模式参数来显式声明。


一般来说python假定处理的是文件文件(包含字符)。通常这样做不会有任何问题。但
如果处理的是一些其他类型的文件(二进制文件)。比如声音剪辑或者图像,那么应该
在模式参数中增加'b'。参数'rb'可以用来读取一个二进制文件。


11.1.2 缓冲
open函数的第3个参数(可选)控制着文件的缓冲。如果参数是0或False就是无缓冲的,
所有的读写操作都直接针对硬盘。如果是1或者True,就是有缓冲的,python使用内存
来代替硬盘,让程序更快,只有使用flush或者close时才会更新硬盘上的数据。大于1
的数字代表缓冲区的大小(单位是字节),-1(或者是任何负数)代表使用默认的缓冲
区大小。


11.2 基本文件方法
接下来会介绍文件对象(和一些类文件对象,有时称为流)的一些基本方法。
类文件对象是支持一些文件的方法的对象,比如file方法,更重要的是支持read方法
或者write方法,或者两者都有。由urllib.urlopen返回的对象是一个很好的例子。它
们支持的方法有read,readline和readlines。


11.2.1 读和写
文件(或流)最重要的能力是提供或者接受数据。如果有一个名为f的类文件对象,那么
就可以用f.write方法和f.read方法(以字符串形式)写入和读取数据。
每次调用f.write(string)时,所提供的参数string会被追加到文件中已存在部分的后面。
>>f.open("somefile.txt", "w")
>>f.write("hello")
>>f.write("World!")
>>f.close()
在完成了对一个文件的操作时,调用close。
读取很简单,只要记得告诉流要读多少个字符(字节)即可。
在调用open时可以省略模式说明,因为"r"是默认的。


11.2.2 管式输出
在UNIX的shell(就像GNU bash)中,使用管道可以在一个命令后面续写其他的多个命令,
如下:(假设是GNU bash)
$ cat somefile.txt | python somescript.py | sort
管道符号(|)将一个命令的标准输出和下一个命令的标准输入连接在一起。


可以使用类文件对象seek和tell来直接访问感兴趣的部分。(这种做法称为随机访问)。


11.2.3 读写行
可以使用file.readline读取单独的一行(从当前的位置开始直到一个换行符出现,也
读取这个换行符)。或者使用一个非负的整数作为readline可以读取的字符(或字节)
的最大值。


11.2.4 关闭文件
应该牢记使用close方法关闭文件。
如果想确保文件被关闭了,应该使用try/finally语句,并且在finally子句中调用close
方法。


11.3 对文件内容进行迭代
read,readline和readlines,另一些方法是我即将介绍的(比如xreadlines和文件迭代
器)。


11.3.1 按字节处理
最常见的对文件内容进行迭代的方法是在while循环中使用read方法。例如,对每个字符
(字节)进行循环,如下:
f = open(filename)
char = f.read(1)
while char:
process(char)
char = f.read(1)
f.close()


当到达文件的末尾时,read方法返回一个空的字符串。
代码重复通常被认为是一件坏事,(懒惰是美德,还记得吗)。
我们可以如下改进:
f = open(filename)
while true:
char = f.read(1)
if not char: break;
process(char)
f.close()


11.3.2 按行操作
处理行使用的方法和处理字符一样,即使用readline方法。
f = open(filename)
while true:
line = f.readline()
if not line: 
break
process(line)
f.close()


11.3.3 读取所有内容
如果文件不是很大,那么可以使用不带参数的read方法一次读取整个文件(把整个文件
当作一个字符串来读取),或者使用readlines方法(把文件读入一个字符串列表,在
列表中每个字符串就是一行)。
用read迭代每个字符:
f = open(filename)
for char in f.read():
process(char)
f.close()


用readlines迭代行:
f = open(filename)
for line in f.readlines():
process(line)
f.close()


11.3.4 使用fileinput实现懒惰行迭代
import fileinput
for line in fileinput.input(filename):
process(line)


11.3.5 文件迭代器
在python的近几个版本中,文件对象是可迭代的,这就意味着可以直接在for循环中使用
它们,从而对它们进行迭代。
f = open(filename)
for line in f:
process(line)
f.close()
下面例子并没有把一个打开的文件赋给变量(就像我们在其他例子中使用的变量f),因
此也就没有办法显式地关闭文件。
for line in open(filename):
process(line)
注意sys.stdin是可迭代的,就像其他的文件对象。因此如果想要迭代标准输入中的所有
行可以按如下形式使用sys.stdin。
import sys
for line in sys.stdin:
process(line)


标准流。3个标准文件对象(在sys模块中的stdin,stdout和stderr)是一个类文件对象。




第12章 图形用户界面
本章简要介绍最成熟的跨平台python GUI工具包---wxPython。
12.1 丰富的平台
wxpython 基于wxWindows,跨平台越来越流行。
PythonWin 只能在Windows上使用。使用了本机的Windows GUI功能。
Java Swing 只能用于Jython。使用本机的java GUI。
PyGTK 使用GTK平台,在Linux上很流行
PyQt 使用Qt平台,跨平台。


编写wxPython程序的方法很多,但不可避免的事情是创建应用程序对象。基本的应用
程序类叫做ex.App,它负责幕后所有的初始化。最简单的wxPython程序应用像下面这样:
import wx
app = wx.App()
app.MainLoop()


可以看到wx包中的方法都是以大写字母开头的,而这和Python的习惯是相反的。这样
做的原因是这些方法名和基础的C++包wxWidgets中的方法名都是对应的。


12.3.2 窗口和组件
窗口(Window)也称为框架Frame,它只是wx.Frame类的实例。wx框架中的部件都是由它
们的父部件作为构造函数的第一个参数创建的。如果正在创建一个单独的窗口,就不
需要考虑父部件,使用None即可。而且在调用app.MainLoop前需要调用窗口的Show方法
否则它会一直隐藏。
import wx
app = wx.App()
win = wx.Frame(None)
win.Show()
app.MainLoop()


在框架上增加按钮也很简单---只要使用win作为父参数实例化wx.Button即可。


12.3.3 标签、标题和位置
可以在创建部件的时候使用构造函数的label参数设定它们的标签。同样,也可以用
title参数设定框架的标题。


一个很基础(但是不实用)的方法是使用pos和size参数在构造函数内设置位置和尺寸。
如下:
import wx
app = wx.App()
win = wx.Frame(None, title="Simple Editor", size=(410, 335))
win.Show()
loadButton = wx.Button(win, label="Open", pos=(225, 5), size=(80, 25))
saveButton = wx.Button(win, label="Save", pos=(315, 5), size=(80, 25))
filename = wx.TextCtrl(win, pos=(5, 5), size=(210, 25))
contents = wx.TextCtro(win, pos=(5, 35), size=(390, 260), style=
wx.TE_MULTILINE|wx.HSCROLL)
app.MainLoop()


12.3.4 更智能的布局
在wx内进行布局的最简单方法是使用尺寸器sizer,最简单使用的工具就是wx.BoxSizer。
尺寸器会管理组件的尺寸。只要将部件添加到尺寸器上,再加上一些布局参数,然后
让尺寸器自己去管理父组件的尺寸。在上面的例子中,需要增加背景组件wx.Panel,创
建一些嵌套的wx.BoxSizer,然后使用面板的SetSizer方法设定它的尺寸器。
代码如下:
import wx
app = wx.App()
win = wx.Frame(None, title="Simple Editor", size=(410, 335))
bkg = wx.Panel(win)


loadButton = wx.Button(bkg, label="Open")
saveButton = wx.Button(bkg, label="Save")
filename = wx.TextCtrl(bkg)
contents = wx.TextCtrl(bkg, style = wx.TE_MULTILINE|wx.HSCROLL)


hbox = wx.BoxSizer()
hbox.Add(filename, proportion = 1, flag = wx.EXPAND)
hbox.Add(loadButton, proportion = 0, flag = wx.LEFT, border = 5)
hbox.Add(saveBuggon, proportion = 0, flag = wx.LEFT, border = 5)


vbox = wx.BoxSizer(wx.VERTICAL)
vbox.Add(hbox, proportion = 0, flag= wx.EXPAND|wx.ALL, border = 5)
vbox.Add(contents, proportion = 1, flag = wx.EXPAND|wx.LEFT|wx.BOTTOM|
wx.RIGHT, border = 5)
bkg.SetSizer(vbox)
win.Show()
app.MainLoop()


wx.BoxSizer的构造函数带有一个决定它是水平还是垂直的参数(wx.HORIZONTAL或者
wx.VERTICAL),默认为水平。Add方法有几个参数,proportion参数根据在窗口改变
大小时所分配的窗口设置比例。
flag参数类似于构造函数中的style参数。


12.3.5 事件处理
在GUI术语中,用户执行的动作比如点击按钮叫做事件event。
利用部件的Bind方法可以将事件处理函数链接到给定的事件上。


14.3 多连接
到目前为止讨论的服务器解决方案都是同步的:即一次只能连接一个客户机并处理它的
请求。
有3种主要的方法能实现同时处理多个连接:分叉(forking),线程(thrreading)以及异步
I/O(asynchronous I/O)。Twisted是一个非常强大的异步网络编程框架。
windows不支持分叉。


14.3.1 使用SocketServer进行分叉和线程处理
使用了分叉技术的服务器
from SocketServer import TCPServer, ForkingMinIn, StreamRequestHandler


class Server(ForkingMinIn, TCPServer):pass


class Handler(StreamRequestHandler):
def handle(self):
addr = self.request.getpeername()
print "Got connection from", addr
self.wfile.write("Thank you for connecting")
server = Server(("", 1234), Handler)
server.server_forever()


一个使用了线程处理的服务器:
from SocketServer import TCPServer, ThreadingMixIn, StreamRequestHandler


class Server(ThreadingMixIn, TCPServer):pass


class Handler(StreamRequestHandler):
def handle(self):
add = self.request.getpeername()
print "Got connection from", addr
self.wfile.write("Thank you for connecting")
server = Server(("",1234), Handler)
server.serve_forever()


14.3.2 带有select和poll的异步I/O
asyncor/asynchat框架和Twisted框架采用方法是只监听(或读取)一会儿,然后把它
放到其他客户端的后面。
这种功能的基础是select函数,如果poll函数可用,也可以是它,它两个函数都来自
select模块。但在windows不能使用poll,它只能在UNIX系统中使用。


一般来说不允许CGI脚本修改计算机上的任何文件。


15.2.5 简单的CGI脚本
15.2.6 使用cgitb调试
注意,应用开发完成后关掉cgitb功能,因为回溯页不是为程序的一般用户准备的。


15.2.7 使用cgi模块
输入是通过HTML表单提供给CGI脚本的键--值对,或称字段。可以使用cgi模块的
FieldStorage类从CGI脚本中获取这些字段。当创建FieldStorage实例时(应该只创建
一个),它会从请求中获取输入变量(或者字段),然后通过类字典接口将它们提供给
程序。


如果知道请求中包括名为name的值,就应该像下面这样做:
form = cgi.FieldStroage()
name = form["name"].value
获取值的简单方式就是用getvalue方法。它类似于字典的get方法。


15.2.8 简单的表单
更多有关编写HTML表单(或者HTML)的信息,应该写本关于HTML的好书来看一下。


15.3 更进一步:mod_python
如果喜欢CGI,那么你可能会爱上mod_python。它是Apache网络服务器的扩展(模块)、
使用mod_python处理程序框架可以访问丰富的API,深入Apache内核等。


15.3.3 PSP
如果用过PHP(Hyptertext Preprocessor,超文件预处理程序,原来称为Personal Home
Page Tools,即个人主页工具或PHP工具),Microsoft ASP(Active Server Page,
活动服务器页面),JSP(Java Server Page,Java服务器页面)或其他类似的技术的话。
PSP(Python Server Page,Python服务器页面)。




15.5.1 RSS和相关内容
RSS代表富站点摘要(Rich Site Summary)、RDF站点摘要或简易信息聚合(Really
Simple Syndication)


15.5.2 使用XML-RPC进行远程过程调用
除了简单地下载和解析之外,RSS还可以进行远程过程调用。


专门为Python设计的开发工具,除了XML-RPC以外,还有Pyro和Twisted的远程过程调用
机制。


15.5.3 SOAP
SOAP是一种使用XML和HTTP作为底层技术的信息交换协议。SOAP原来的全称为简单对象
访问协议Simple Object Access Protocol。就像XML-RPC一样,SOAP支持远程过程调用,
但SOAP规范比XML-RPC规范复杂得多。SOAP是异步的,支持与路由有关的元请求,并且
拥有复杂的类型系统(同XML-RPC简单的固定类型集相反)。


目前没有专门为python开发的标准SOAP工具包,可以考虑使用Twisted、ZSI、或SOAPy。




第16章 测试
Python内是没有编译步骤的--所以只需要编辑和运行即可。运行程序就是测试的过程。
除了标准库中的测试和分析profiling工具外,本章还会介绍如何使用代码分析器
PyChecker和PyLint。


16.1 先测试,后编码
这种编程方式也被称为测试驱动编程。Test-driven programming。


16.1.1 精确的需求说明。


16.1.2 为改变而计划


16.2 测试工具
有两个很有用的模块:
unitest:通用测试框架
doctest:简单一些的模块,是检查文档用的,但是对于编写单元测试也很在行。


16.2.1 doctest


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值