您的位置:首页 > 编程语言 > Python开发

《Python How to Program》读书笔记

2013-01-20 14:34 381 查看
前言

Python是一种强大的常规用途语言,尤其适合开发基于Internet和Web的、数据库密集型的、多层的客户机/服务器系统。

第1章 绪论

Python源代码、模块和文档资料的主要“集散地”是Python网站(www.python.org)。

第2章 Python编程概述

1.注释以#开头,并且只有单行注释

2.如何调试程序?在交互模式下一次执行一条语句吗?

3.会使用print,raw_input,int

4.标识符区分大小写

5.Python使用的是“动态类型定义”技术,即在程序执行期间决定一个对象的类型(即赋给它的是什么类型的值,它就是什么类型)。

6.

** 求幂运算符,即3 ** 2 = 9

/ Floor除法, 即5 / 2 = 2.5

// True除法, 即5 / 2 = 2

但是要记得先执行from __future__ import division,否则会根据操作数类型来决定是什么除法

7.常用的格式化字符串

如果想在字符串中使用"但不采用转义字符,则可以使用'字符串,类似的

如果想在字符串中使用'但不采用转义字符,则可以使用"字符串,类似的

如果想在字符串中使用'和"都不采用转义字符,则可以使用"""字符串,"""字符串还可以用于大型的文本块,因为三引号字符串可跨越多行。本书中,实例程序要为Web输出大的文本块时,就会使用三引号字符串。例:

print"""abc

123"""

输出:

abc

123

格式化字符串时,转换指示符符号和C++中基本一样,差别主要在使用上,比如

print "sum is %d" % 100

print "a = %d, b = %d" % (1, 2) #记得加括号,否则语法错误

8.学会使用if语句

if 2 == 2 :

print "test if"

print "test end"

a.不要忘记在条件后面加:了

b.以缩进确定执行块,而在C++中可以用{}

c.如果有多个条件如何写?是不是也有逻辑运算符?(见后面的and or not)

9.续行符和C++中一样,也是\

例:

print "a\

b"

输出:

ab

第3章 控制结构

1.Python关键字

and continue else for import not raise

assert def except from in or return

break del exec global is pass try

class elif finally if lambda print while

2.学会使用if,if/else,if/elif/else结构

例:

if grade >= 60:

print "Passed"

else:

print "Failed"

例:

if grade >= 90:

print "A"

elif grade >= 80:

print "B"

else:

print "C"

3.对于空语句,可以用pass,相当于C++中的;

例:

if 1 == 1:

pass

4.while结构

例:

product = 2

while product < 1000:

product = product * 2

print product # 1024

3.for结构

for i in range(0, 5, 1):

print

range有三种情况,

range(5) 表示从0开始,到4结束

range(0, 5) 表示从0开始,到4结束

range(0, 5, 1)表示从0开始,到4结束,步长为1

4.逻辑运算符and or not

例:

if 1==1 and 2==2:

print "true"

第4章 函数

1.Python的程序组件包括函数、类、模块和包。Python模块提供了用于执行常见任务的函数,比如数学计算、字符串处理、字符处理、Web编程、图形编程和其他许多操作。这些模块在Windows上位于\Python25\Lib下。

2.如何使用标准库中提供的函数?



import math

print math.sqrt(900)

import用来导入math模块,这样我们就可以使用其中的函数和变量,相当于C++中的包含头文件,或者说打开math这个命名空间,类似于using namespace std;

调用函数时记得加模块名math

3.如何查看标准库中某个模块包含的函数及用法?

打开Module Docs,输入math,点击open browser,在打开的页面中点击math,就可以看到它包括的函数及用法了。

4.如何调用我们自己写的模块?

5.如何定义自己的函数

# def

def square(y):

print y*y

# use

square(2)

print square # print address of square function

输出:

4

<function square at 0x00DC7530>

5.如何查看某个命名空间中的标识符?

在交互模式下,调用dir函数,



>>> dir()

输出:

['__builtins__', '__doc__', '__name__', 'math', 'square', 'x']

其中,square、x在前面定义过,math被import过,'__builtins__', '__doc__', '__name__', 是当前命名空间固有的



>>> import math

>>> dir(math)

输出:

['__doc__', '__name__', 'acos', 'asin', 'atan', 'atan2', 'ceil', 'cos', 'cosh', 'degrees', 'e', 'exp', 'fabs', 'floor', 'fmod', 'frexp', 'hypot', 'ldexp', 'log', 'log10', 'modf', 'pi', 'pow', 'radians', 'sin', 'sinh', 'sqrt', 'tan', 'tanh']

6.作用域

例1:

x = 10

def test():

x = 1

print x # 1,默认引用局部的

test()

例2:

x = 10

def test():

global x # 告诉引用全局的x

print x

test()

7.import的用法

import math,random #将math和random导入

from math import sqrt,cos #仅仅导入sqrt和cos函数

import random as randomModule #导入random但是更名为randomModule

from math import sqrt as squareRoot #导入sqrt函数并更名为squareRoot,这样我们就可以直接调用squareRoot,而不用加math.了

8.函数的默认参数,和C++中一样,略

9.关键字参数



def boxVolume(length = 1, width = 2, height = 5):

print length * width * height

boxVolume(height = 1, length = 2)

输出:

4

简单一点说就是在调用函数的时候实参把形参带上,这样就实参传入的顺序就不依赖于参数列表顺序了,例子中,因为没有传入width,所以width取默认值2

第5章 列表、元组和字典

1.Python支持3种基本序列数据类型:字符串(string)、列表(list)和元组(tuple)。Python支持一种映射数据类型:字典(dictionary)(相当于C++中的map)。第22章还要介绍一些高级数据结构链表、序列、堆栈和树)。

2.序列(相当于C++中的vector)的下标也是从零开始,不过它可以用负数作为下标访问,如果元素个数为n,则第一个元素的下标可以为0,也可以为-(n - 0),依次类推。当是负数时,可以理解为倒数第几个元素,比如-1则是倒数第一个元素。

要求序列元素的个数,可以用函数len。

3.如何创建序列

不同的Python序列(字符串、列表和元组)需要不同的语法。

a.创建字符串

aString = "abc"

b.创建列表

aList = [1, 2, 3]

c.创建元组

aTuple = () # 空元组

aTuple = 1, 2, 3 # 包含值序列的元组

aTuple = (1, 2, 3) # 也可以用小括号括起来,和上面实际是一样的。记住,创建元组的是逗号,而非园括号。

aTuple = 1, # 创建单元素元组,记得加逗号,否则aTuple就成为整形变量了

4.使用列表

列表一般包含同种数据类型。列表的长度一般是事先为确定的,并可在程序执行期间发生改变。(从这一点说更像vector,而不是数组)

例:

aList = []

for number in range(1, 11):

aList += [number]

for item in aList:

print item

输出:

1

2

3

4

5

6

7

8

9

10

5.使用元组

元组通常存储异常数据类型的序列-但这只是一种习惯,而非规则。列表和元组的主要区别在于,列表是可变的,元组则是不可变的(包括元素个数和元素的值)。

用多个变量来生成一个序列,我们称之为打包。例如

aTuple = (x, y, z)

aTuple = (1, 2, 3)

元组和其他序列还可以"解包"-将序列中存储的值指派给各个标识符。通过"解包"而在单个语句中为多个变量指派值,是一种简化编程的有效手段。

aString = "abc"

first, second, third = aString

print first, second, third

aList = [1, 2, 3]

first, second, third = aList

print first, second, third

aTuple = ("A", "a" ,3)

first, second, third = aTuple

print first, second, third

输出:

a b c

1 2 3

A a 3

打包和解包的一种应用-交换两个变量的值:

x = 1

y = 2

x, y = y, x

print x, y

输出:

2 1

6.序列分片

简单一点说就是从序列中截取一部分,

sequence[i, j + 1]表示从序列中获取从第i个元素到第j个元素的一个分片,例

aList = [1, 2, 3, 4 ,5]

print aList[1 : 2+1]

输出:

[2, 3]

7.字典

例:

# -*- coding: cp936 -*-

#创建一个空字典

aDictionary = {}

grade = {"john" : 87, "niefuhua" : 100}

print grade

#修改和访问一个已经存在的元素

grade["john"] = 90

print grade["john"]

#添加一个元素

grade["mm"] = 89

print grade

#删除一个元素

del grade["niefuhua"]

print grade

输出:

{'john': 87, 'niefuhua': 100}

90

{'mm': 89, 'john': 90, 'niefuhua': 100}

{'mm': 89, 'john': 90}

注意:如果代码中出现中文,则必须加上# -*- coding: cp936 -*-这句

8.列表方法

也就是列表的成员函数,有append,count,extend,index,insert,pop,remove,reverse,sort,例如

aList = [1, 2, 3]

aList.reverse();

print aList

输出:

[3, 2, 1]

9.字典方法

clear,copy,get,has_key等,用的时候再查

例:

aDictionary = {1 : "a", 2 : "b"}

aDictionary.clear()

print aDictionary

输出:

{}

浅拷贝和深拷贝

例:

aDictionary = {1 : "a", 2 : "b"}

aDic2 = aDictionary.copy(); #浅拷贝,相当于aDic2指向的是aDictionary,即引用,修改其中一个会影响另外一个.经过测试,好像不灵,仍然是深拷贝

aDic2[1] = "c"

print aDictionary

输出:

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

例:

import copy

aDictionary = {1 : "a", 2 : "b"}

aDic2 = copy.copy(aDictionary) #按文档上说是浅拷贝,测试发现仍然是深拷贝

aDic2[1] = "c"

print aDictionary

输出:

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

例:

aDictionary = {1 : "a", 2 : "b"}

from copy import deepcopy # 从copy模块中导入deepcopy函数,深拷贝

aDic2 = deepcopy(aDictionary)

aDic2[1] = "c"

print aDictionary

输出:

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

对于

aDictionary = {1 : "a", 2 : "b"}

aDic2 = aDictionary # 书上说是深拷贝,但测试后发现是浅拷贝

aDic2[1] = "c"

print aDictionary

输出:

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

10.按引用传递参数

书上原话:和其他许多语言不同,传递参数时,Python不允许程序员选择采用传值还是传引用。Python参数采用的肯定是“传对象引用”的方式,即函数收到的是对作为参数传递的值的一个引用。实际上,这种方式相当于传值和传引用的一种综合。如函数收到对一个可变对象(比如字典或列表)的引用,就能修改对象的原始值-相当于通过“传引用”来传递对象。如函数收到对一个不可变对象(比如数字,字符串或者元组)的引用,函数就不能直接修改原始对象-相当于“传值”来传递对象。

其实上面的话不好理解,还不如说是按参数的类型来决定是什么传参方式呢。通过下面我自己写的程序可以证明上面描述的传参方式是正确的。(未写例子打死我都不能相信上面的话)

例:

def modifyList(aList):

for i in range(len(aList)):

aList[i] *= 2

aList = [1, 2, 3, 4, 5]

modifyList(aList) #因为aList的元素个数是可变的,故相当于引用

print aList

输出:

[2, 4, 6, 8, 10]

例:

def modifyElement(element):

element *= 2

elems = (1, 2, 3)

modifyElement(elems) #因为elems是元组,其元素个数是不可变的,故相当于传值

print elems

输出:

(1, 2, 3)



i = 4

modifyElement(i) #因为i可以算成只有一个元素的列表,故相当于传值

print i

输出:

4

11.多下标序列

例:

table = [[1, 2, 3], [4, 5, 6]]

for row in table:

for item in row:

print item

输出:

1

2

3

4

5

6

第6章 公共网关接口(CGI)入门

1.

CGI之所以是"公共"的,是因为它不依赖于任何操作系统(无论是Linux还是Windows),也不依赖于任何程序语言或任何Web服务器软件(比如IIS,Apache).CGI可用于几乎任何程序语言或脚本语言,比如C,Perl和Python.

用户输入URL时,客户端必须发出资源请求。两种最常见的HTTP请求类型(也称为请求方法)是get和post。

大多数Web服务器都将get请求查询字符串限制在1024个字符以内。如果查询字符串超过这一限制,就必须使用post请求。

Web应用程序采用两类脚本编程:服务器端和客户端。CGI脚本是服务器端脚本的一个例子,因其在服务器上运行。使用服务器端脚本,程序员对网页能有更大的控制,因为这种脚本可操纵数据库和其它服务器资源。客户端脚本编程的一个例子是JavaScript。客户端脚本可使用浏览器功能、处理浏览器文档以及校验用户输入等。

服务器上执行的脚本通常为客户生成自定义的响应。比如根据请求中查询条件,动态生成网页内容,并将其发送给客户。

相较于客户端脚本语言,服务器端脚本语言提供更广泛的编程能力。例如,服务器端脚本可访问服务器的目录结构,而客户端脚本无此权限。

服务器端脚本还可以访问服务器端软件,以扩展服务器的功能。对于Microsoft Web服务器,这些软件称为“COM组件”;对于Apache Web服务器,则称为“模块”。组件和模块的范围很广,从程序语言支持,一直到网页计数器。

例:

#!c:\Python\python.exe #指出Python解释器的位置

#Displays current date and time in Web browser.

import time

def printHeader(title):

print """Content-type: text/html

<?xml version = "1.0" encoding = "UTF-8"?>

<!DOCTYPE html PUBLIC

"-//W3C//DTD XHTML 1.0 Strict//EN"

"DTD/XHTML1-strict.dtd">

<html xmlns = "http://www.w3c.org/1999/xhtml">

<head><title>%s</title></head>

<body>""" % title

printHeader("Current date and time")

print time.ctime(time.time())

print "</body></html>"

常见编程错误:运行脚本的Web服务器不理解.py扩展名时,忘记在CGI脚本第一行添加预编译指令(#!),是错误的.

注意,程序几乎完全由print语句构成.到目前为止,print的输出都是在屏幕上显示的.但是,从技术角度说,print的目标是"标准输出"-由应用程序提供给用户的一个信息流.通常,标准输出在屏幕上显示,但也可发送给打印机,写到一个文件等等.Python程序作为一个CGI脚本执行时,服务器将标准重定向至客户端的Web浏览器.浏览器对头和标记进行解释,把它们当作是服务器对XHTML文档请求的一个普通响应.

程序想要执行,必须正确配置服务器.注意,本书使用的是Apache Web服务器,要详细了解如何获得和配置Apache,请参考我们在www.deitel.com公布的Python Web资源.一旦服务器可用,Web站点管理员就需要指定CGI脚本位于何处,以及它们使用的名字.在我们的例子中,Python文件放在Web服务器的cgi-bin目录.

假定服务器位于本地计算机上,为执行程序,可在浏览器的"地址"栏中输入:
http://localhost/cgi-bin/fig06_02.py
如果服务器位于不同计算机上,请将localhost替换成服务器的主机名或IP地址.服务器分辨出客户端请求的资源是一个Python脚本,所以它调用Python解释器来执行脚本.程序执行后,发送给标准输出的文本会返回给Web服务器.最后,Web服务器在输出中打印附加的一行,指出HTTP事务处理的状态(比如HTTP/1.1 200 OK表明成功),再将完整的文本主体发送给客户.

总结上面的过程:

1.get请求(GET /cgi-bin/fig06_02.py HTTP/1.1)从客户发送给Web服务器->

2.收到请求后,Web服务器在系统中搜索资源(fig06_02.py)->

3.CGI脚本运行,创建输出

4.脚本输出发送回Web服务器

5.Web服务器用一条恰当的消息响应请求(HTTP/1.1 200 OK),随附CGI脚本执行后的输出

2.向CGI脚本发送输入

也得简单一点就是客户发送的查询条件如何让脚本知道?通过QUERY_STRING做到.

例如如下URL:

www.somesite.com/cgi-bin/script.py?state=California

会导致Web浏览器从www.somesite.com请求一个资源.资源要通过执行CGI脚本(cgi-bin/script.py)来生成,问号(?)之后的信息(state=California)由Web服务器指派给QUERY_STRING环境变量.注意,问号本身并非所请求资源的一部分,也不是查询字符串的一部分,它只是资源和查询字符串之间的分隔符.

然后,在脚本中,我们就可以通过

query = os.environ["QUERY_STRING"]

来获取查询条件.

3.用XHTML表单发送输入并用cgi模块获取表单数据

用户不可能在每次访问一个页面的时,都亲自在URL中输入CGI脚本需要的所有信息.XHTML允许在网页中包含一个表单,利用它可更只观地输入CGI脚本需要的信息.

简单一点说,就是在网页中放一些控件,当用户输入一些东西后,触发一些事件,事件中可能包含了要即将要执行的CGI脚本,相当于把直接在URL中输入查询条件变通为通过程序产生查询条件.比如,网页中有一个文本框state,当用户输入California后,点击提交,部分代码如下:

<form method = "get" action = "fig06_08.py">

<p>

<input type = "text" name = "state" />

......

浏览器就会自动产生

www.somesite.com/cgi-bin/fig06_08.py?state=California

这种形式的GET请求,并发送到Web服务器.

挑战:搭建一个Web服务器,并实现Python脚本产生动态网页,这样可以的话,这章就算过关了!

第7章 基于对象的编程

1.例:

# Fig test1.py

class Test:

"""test class"""

def __init__(self):

"""this is constructor"""

self._hour = 0 #定义了类的一个属性,属性名一般都以单下划线开头

print "Constructor"

def myfun(self):

print "myfun"

#Fig test2.py

from test1 import Test

t = Test()

t.myfun()

为什么说找不到Test?妈的

注意:

1.类名首字母必须得大写

2."""this is constructor"""是类的可选的“文档化字符串”,它描述了类。要想包含文档化字符串,该字符串必须位于紧接在类头之后的一行或多行中。要查看类的文档化字符串,应执行以下语句:

print ClassName.__doc__

模块,方法和函数也可以指定一个文档化字符串

3.忘记将对象引用(通常是self参数)设为方法定义中的第一个参数,会导致该方法在运行时被调用时,造成严重的逻辑错误.(看起来跟this指针差不多,呵呵)

4.调用方法时,不用给self传递实参

5.以单下划线开头的属性揭示一个类的接口的相关信息.类如果定义了此类属性,它的客户就只能通过类提供的访问方法(比如set/get)来访问并修改属性值.如果不这样做,通常会导致程序执行期间出现不可预料的错误.

6.在Python中处理无效属性值时,异常是首选的技术

2.如何抛异常

raise ValueError, "This is an error message"

3.私有属性

在Python中,对象的属性是肯定能访问的-没有办法阻止其他代码访问数据.然而,Python提供了一种特别的机制来防止任意访问数据.假定要创建Time类的一个对象,并希望阻止以下赋值语句:

time1.hour = 25

就可以考虑为属性名附加双下划线(__).Python遇到以双下划线开头的属性名时,解释器会对属性执行"名称重整"(name Mangling)操作,禁止对数据的任意访问.例如

# Fig test1.py

class Time:

def __init__(self):

__hour = 0

time1 = Time()

time1.__hour = 5 #为什么不能加这句?加了书上说的就不灵了,不加就和书上说的一样

print time1.__hour #按书上说,应该这样不能访问,但实际能

print time1._Time__hour #按书上说,应该这样才能访问,但实际上反而不行

为什么书上那么多和实际不一致的呢?

4.析构函数

类可以定义名为__del__的一个特殊方法,它在最后一个对象引用删除或超过作用域之后执行.析构函数通常只指定self参数,并返回NONE.

在C++等程序语言中,析构函数通常用于分配和回收内存.Python为程序员解决了大多数这样的问题,所以通常不在类定义中包含__del__.偶尔,类会定义__del__来关闭网络或数据库连接.

5.类属性(实际相当于类的静态成员变量)

例:

# Fig test1.py

class Time:

count = 5

print Time.count #在类主体中定义,而不是在构造函数中,不产生对象也可以使用

第8章 自定义类

1.如果想print一个类,我们可以给这个类添加一个__str__方法,在函数中返回的字符串是什么,print该类的时候就显示什么.例:

class PhoneNumber:

def __init__(self, number):

self.num = number

def __str__(self):

return "%s" % self.num

phone = PhoneNumber("13926543314")

print phone

print "The Phone Number is %s" % phone #同样会调用__str__

输出:

13926543314

The Phone Number is 13926543314

2.在获取属性值,设置属性值,删除一个属性时会执行的函数介绍



# -*- coding: cp936 -*-

class Time:

def __init__(self, hour):

self._hour = hour #调用__setattr__,将_hour和hour分别赋给name,value

def __getattr__(self, name):

print name

if name == "_hour1":

return 7

def __setattr__(self, name, value):

print name

print value

if 0 <= value <= 6:

self.__dict__["_hour"] = 24 #不能再用self._hour = 24,否则就是死循环

def test(self):

hour = self._hour

hour = self._hour1

print hour

time1 = Time(1)

time1.test()

输出:

_hour

1

_hour1

7

执行过程:Time(1)导致__init__被调用,self._hour = hour导致__setattr__被调用(打印_hour, 1),执行完__setattr__后,_hour等于24.

调用time1.test()时,首先执行hour = self._hour,Python首先会在time1的__dict__属性中查找指定的属性名_hour,如果找到就将其值赋给hour(找到了,所以__getattr__未被调用),如果没找到(比如self._hour1),Python就会触发__getattr__函数(打印_hour1),并且它返回什么值(7)就会把什么值给hour(所以print hour打印7).

对于大型系统,如果需要严格的数据访问,设计者就应使用__getattr__,__setattr__来确保数据的完整性.

3.重载运算符

要想重载运算符,需要和往常一样写一个方法定义,只是方法名要与用于运算符的Python特殊方法对应.例如,要重载+运算符,需要实现__add__函数.

如果重载一元算术运算符(例如,+ - *),会自动重载与运算符对应的增量赋值语句(相当于自动重载了+= -= *=运算符)

常见的名字:

__pos__

__neg__

__invert__

__add__

__sub__

__mul__

等等

例:

class Int:

def __init__(self, val):

self._val = val

def __add__(self, int):

return Int(self._val + int._val)

def __str__(self):

return "%s" % self._val

a = Int(4) + Int(5) #因为实现了__add__,所以+可用

print a

a += Int(1) #重载+后,+=被自动重载

print a

输出:

9

10

4.重载内建函数

类也可以定义某些特殊方法.一旦针对类的一个对象调用特定内建函数,就执行这些方法.例如,可为Rational类定义特殊方法__abs__,一旦程序调用abs(rationalObject)来计算那个类的一个对象的绝对值,便执行__abs__.

下面总结了常用的内建函数以及可由类定义的特殊方法:

__abs__

__divmod__

__len__

__pow__

__repr__

例:

class Int:

def __init__(self, val):

self._val = val

def __abs__(self): #和下面的__long__及上面的__add__都是同样道理,不用把它看着特殊一类重载

if self._val < 0 :

return -self._val

else :

return self._val

i = Int(-25)

print abs(i)

输出:

25

5.类型转换

比如要将一个类对象转换为int类型,则需要为类定义__int__方法.

例:

class Int:

def __init__(self, val):

self._val = val

def __int__(self):

return self._val #当调用int时,int()返回值就是这儿的返回值

i = Int(2)

print int(i)

输出:

2

常用的内建函数名:

__conerce__

__complex__

__float__

__hex__

__int__

__long__

__oct__

__str__

6.重载序列运算符

例:

class Int:

def __init__(self, val):

self._val = val

def __len__(self):

return 1

i = Int(-25)

print len(i)

输出:

1

实际上,Int并不是一个序列,但是只要我重载了__len__,调用len(i)时,Python就会调用Int的__len__成员函数.还是和上面的重载同样的道理,没什么看头!

常用的方法:

__add__

__append__

__contains__

__count__



7.重载map运算符

和上面的同理,例:

class Int:

def __getitem__(self, key):

return key

i = Int()

print i[1]

输出:

1

在重载的时候,最好不要让被重载的运算符或函数失去本身的意思,比如上面的__getitem__,本来应该用在map结构中,我却随便搞了一个类让其重载,这样就失去重载的意义!

上面的例子仅仅是演示如何重载,所以没关系.

第9章 面向对象编程:继承

1. 基类和派生类

例,如何继承

# -*- coding: cp936 -*-

import math

class Point:

def __init__(self, xValue = 0, yValue = 0):

self.x = xValue

self.y = yValue

def __str__(self):

print "Point"

return "Point"

class Circle(Point): #表示继承自Point类

def __init__(self, x = 0, y = 0, radiusValue = 0.0):

Point.__init__(self, x, y) #如果子类覆盖了父类的__init__,必须显式调用基类的构造函数,不要忘了实参self

self.radius = radiusValue

def __str__(self):

Point.__str__(self) #如何调用基类版本函数

return "Circle"

def area(self):

return math.pi * self.radius ** 2

#main program

print Point.__bases__

print Circle.__bases__

print issubclass(Circle, Point) #判断Circle是否是Point的子类

point = Point(30, 50)

circle = Circle(120, 89, 2.7)

print isinstance(circle, Point) #判断circle对象是否是Point的一个实例,返回True

print isinstance(point, Circle) #判断point对象是否是Circle的一个实例,返回False

print point.__dict__

print circle.__dict__

print circle.area()

p = Circle(56, 78, 9)

print p #调用子类的__str__函数,即Python天生具有多态特性

输出:

()

(<class __main__.Point at 0x00DC6540>,)

True

True

False

{'y': 50, 'x': 30}

{'y': 89, 'x': 120, 'radius': 2.7000000000000002}

22.9022104447

Point

Circle

2.抽象基类

# -*- coding: cp936 -*-

import math

class Point:

def __init__(self):

if self.__class__ == Point: #如果发现是自己的实例,则抛出异常,确保不能创建它自己的实例,从而实现抽象基类,呵呵,和C++不同的是,它是运行时才能检测出是否是创建了抽象基类的实例

raise NotImplementedError, "Can't create object of class Emplyee"

def test(self):

raise NoImplementedError, "can't call abstract method"

class Circle(Point):

def __init__(self):

Point.__init__(self)

print "Circle __init__"

def test(self):

print "Implement class's method"

#main program

point = Circle()

point.test()

3.静态方法



# -*- coding: cp936 -*-

import math

class Point:

count = 5 #静态成员变量

def p():

print Point.count #如何访问静态成员变量

pp = staticmethod(p) #指定p是静态成员方法,并指定pp是p函数的别名,外界调用的时候就只能用pp,一般我们都把p和pp搞成一样的

#main program

point = Point();

point.pp()

Point.pp()

4.我们还可以从内建类型继承

# -*- coding: cp936 -*-

import math

class Point(long): #可以从内建类型继承

count = 5 #空类不能运行,无论如何都要给类加点东西

#main program

point = Point();

print point #调用long的__str__函数

5.__slot__属性

Python的灵活性所带来的一个副作用是,在对象创建好之后,程序仍可在对象的命名空间中添加属性.这有时会招致不可预料的结果.为了解决这个问题,Python2.2允许新类定义一个__slot__属性,它可列出只允许类的对象拥有的属性.

比如

class PointWithSlots(object):

__slot__ = ["x", "y"]

后,你就只能往PointWithSlots中添加x,y属性,添加其他的就会Python就会报错,试了一下,没成功

6.属性关键字property

对于一个属性成员,一般都有set,get,delete,字符串文档化字符串四个东东,如果分开写的话,我们就需要创建三个函数setXX,getXX, delXX,而通过property我们可以一步完成这些过程.

例:

second = property(getSecond, setSecond, deleteSecond, "Second")

太累了,这儿没搞懂,睡觉了

第10章 图形用户界面组件(一)

1.Python程序员可用“工具命令语言”(Tool Command Language, Tcl)程序及其图形图形界面开发工具“工具包”(Tool Kit,TK)来构建GUI。要想了解这种脚本语言及其组件的详情,请访问www.scriptics.com。

Frame Label Entry Text Button Checkbutton Radiobutton Menu Canvas Scale Listbox Menubutton Scrollbar

2.Python中通常用Tkinter模块进行GUI编程,因其是Python的标准GUI包,与Python程序配套提供.本章每个程序都通过从Widget的子类Frame继承,实现了一个GUI.

Tkinker模块可为Unix、Macintosh和Windows平台设计图形用户界面。

3.例:

# -*- coding: cp936 -*-

from Tkinter import *

from tkMessageBox import *

class GuiDemo(Frame): #相当于从主框架继承

def __init__(self):

Frame.__init__(self) #调用主框架的构造函数

self.pack(expand = YES, fill = BOTH)

self.master.title("Labels") #master相当于取得父组件指针

self.Label1 = Label(self, text = "Label with text")

self.Label1.pack() #将标签加入GuiDemo

self.text1 = Entry(self, name = "text2") #创建一个文本框

self.text1.bind("<Return>", self.showContents) #设置用showContents函数去响应回车事件

self.text1.pack(side = LEFT, padx = 5) #将文本框加入GuiDemo

def showContents(self, event):

theName = event.widget.winfo_name() #取得产生事件的窗口名,对应name = "text2"

theContents = event.widget.get() #取得文本框中的内容

showinfo("Message", theName + ": " + theContents) #显示消息框,showinfo函数来自tkMessageBox模块

def main():

GuiDemo().mainloop() #启动消息循环

if __name__ == "__main__":

main()

这一章都是各种控件的使用,不细究,以后使用的时候再看。

第11章 图形用户界面组件(二)

1.本章讨论“Python Megawidgets,Pmw”组件,它是提供高级GUI组件的一个工具包,是基于由Tkinter模块提供的较小的组件而开发的。

比如

ComboxBox

ScrolledListBox

ScrolledText

MenuBar

弹出菜单

Canvas

Scale

例:

# -*- coding: cp936 -*-

from Tkinter import *

class PopupMenuDemo(Frame):

def __init__(self):

Frame.__init__(self)

self.pack(expand = YES, fill = BOTH)

self.master.title("Popup Menu Demo")

self.master.geometry("200x600") #设置窗口的大小

self.frame1 = Frame(self, bg = "White")

self.frame1.pack(expand = YES, fill = BOTH)

self.menu = Menu(self.frame1, tearoff = 0)

colors = ["White", "Blue", "Yellow", "Red"]

self.selectedColor = StringVar()

self.selectedColor.set(colors[0])

for item in colors:

self.menu.add_radiobutton( label = item, #添加单选菜单,即只能有一个菜单是打勾的

variable = self.selectedColor,

command = self.changeBackgroundColor)

self.frame1.bind("<Button-3>", self.popupMenu) #将popupMenu函数绑定到frame1的右键事件

def popupMenu(self, event):

self.menu.post(event.x_root, event.y_root) #弹出菜单

def changeBackgroundColor(self):

self.frame1.config(bg = self.selectedColor.get())

def main():

PopupMenuDemo().mainloop() #启动消息循环

if __name__ == "__main__":

main()

2.其他GUI工具包

PyGTK

wxPython

PyOpenGL

第12章 异常处理

学习目标

1.理解异常以及错误处理

2.会用try语句对可能引发异常的代码进行定界

3.学会raise异常

4.会用except子句指定异常处理程序

5.会用finally子句释放资源

6.理解Python异常类层次结构

7.理解Python跟踪机制

8.会创建程序员自定义的异常

第13章 字符串处理和正则表达式

学习目标

1.理解Python中的文本处理

2.使用Python的字符串数据类型方法

3.处理和搜索字符串内容

4.理解和创建正则表达式

5.使用正则表达式在字符串中匹配模式

6.使用元字符、特殊序列和分组来创建复杂正则表达式

第14章 文件处理和序列化

学习目标

1.会创建、读取、写入及更新文件

2.熟悉顺序访问文件处理

3.理解通过shelve模块进行的随机访问文件处理

4.会指定高性能、未格式化的I/O操作

5.理解格式化和原始数据文件处理的差异

6.利用随机访问文件处理构建一个事务处理程序

7.序列化复杂对象以便存储

第15章 可扩展标记语言(XML)

学习目标

1.理解XML

2.会用XML标记数据

3.熟悉用XML创建标记语言的类型

4.理解DTD、Schema和XML之间的关系

5.理解基于DOM和基于SAX的解析基础

6.理解XML命名空间的概念

7.会创建简单的XSL文档

1.XML是一种可移植的、获得普遍支持的开放式技术(也就是一种非专利技术),它用于对数据进行描述。XML很快就称为在应用程序之间交换数据的一个标准。使用XML,文档作者可描述任何数据类型的数据,包括数学公式、软件配置指南、乐谱以及财务报表。使用XML的另一个好处在于,不管是人还是机器,都可顺利地阅读文档。

2.

<?xml version = "1.0"?>

<!-- Fig.15.1: article.xml -->

<article>

<title>Simple XML</title>

<author sex = "Male">

<firstName>John</firstName>

<secondName>Doe</secondName>

<flag gender = "M"/>

</author>

</article>

<?xml version = "1.0"?>是一个可选的“XML声明”。尽管XML声明是可选的,但最好通过声明标识所用的XML的版本。否则,未来缺少XML声明的文档会假定为遵循最新的XML版本,从而导致不可预测的错误。

一个XML文档总体上只能由一个元素构成,即“根元素”,其中包含了文档中的其他所有元素。根元素(例如article)必须是XML声明之后的第一个元素。

XML是区分大小写的。记住,不要把XML标记名的大小写形式写错了。

流行的XML解析包包括微软的msxml、4DOM(第16章要全面使用的一个Python包)、Apache Software Foundation的Xerces以及IBM的XML4J。

数据(例如Male)除了能放到标记之间,还可以放到“属性”(例如sex)中,每个元素都可以在起始标记中指定任意数量的属性。属性值必须用双引号或单引号封闭,否则就是错误。

<flag gender = "M"/>叫做空元素,它不包含数据。要想结束这样的元素,要么在元素末尾插入一个正斜杠,要么显示地写一个结束标记,比如<flag gender = "M"></flag>

3.命名空间

为了对相同元素名的元素进行区分,我们可以采用命名空间。

例:

<?xml version = "1.0"?>

<directory xmlns = "http://www.deitel1.com" xmlns:image = "http://www.deitel2.com">

<file filename = "book.xml">

<description>A book list</description>

</file>

<image:file filename = "funny.jpg">

<image:description>A funny picture</image:description>

</image:file>

<directory>

xmlns = "http://www.deitel1.com"创建了一个默认命名空间

xmlns:image = "http://www.deitel2.com"创建了一个名叫image的命名空间

从上面可以看出,通过命名空间,我们区分了拥有同样名字的file元素

4.文档对象模型(DOM)

尽管XML文档本身是文本文件,但通过顺序问文件访问技术从中获取数据,显得既不实际,也没有效率,尤其是在其中的数据需要动态添加或删除的时候。

成功解析文档后,有些XML解析器会将文档数据以树的形式存储到内存中。这个层次化的树结构称为“文档对象模型”树,能够创建这类结构的XML解析器称为“DOM解析器”。XML解析器以可编程的库的形式来提供创建、删除和追加节点功能,还可以载入XML文档。

5.Simple API for XML(SAX)

SAX是解析XML文档的另一种方法,使用的是一个"基于事件的模型".基于SAX的解析器在处理文档时,会生成名为"事件"的通知信息.软件程序可以"侦听"这些事件,以便从文档获取数据.

大量程序语言都可使用基于SAX的解析器,比如Python,Java和C++等等.

针对XML文档数据的访问,SAX和DOM提供了截然不同的API.每种API都有自己的优点和缺点.DOM是一种基于树的模型,将文档数据存储到一个由节点构成的层次结构中.程序可快速访问数据,因为所有文档都在内存中.DOM还提供了相应的机制来增删节点,从而简化了程序对XML文档的修改.

基于SAX的解析器在遇到标记时,要调用"侦听器方法".使用这种基于事件的模型,以SAX为基础的解析器不会创建一个树结构来存储文档数据.相反,在找到数据时,解析器会将数据传给应用程序.相较于基于DOM的解析器,这样可获得更好的性能,内存开销也较小.事实上,许多DOM解析器都在幕后使用SAX解析器,以便从文档中获取数据,并在内存中生成DOM树.许多程序员都认为,使用DOM树结构,可以更容易地遍历及处理XML文档.因此,程序常常用SAX解析器读取不会由程序修改的XML文档.

性能提示15.1 处理大型XML文档时,基于SAX的解析器通常比基于DOM的解析更有效,尤其重要的是,基于SAX的解析器不会将整个XML文档载入内存.

性能提示15.2 如果文档只需读取一次,那么最有效的就是基于SAX的解析.

性能提示15.3 程序要从文档快速获取信息时,DOM解析通常比SAX解析更有效.

性能提示15.4 要求节省内存的程序通常使用基于SAX的解析器.

DOM是正式的W3C推荐规范.

6.文档类型定义(DTD),架构和验证

文档类型定义(DTD)和架构(Schema),即指定了XML文档结构的文档(包括哪些元素是允许的,一个元素可以有什么属性等等).提供了一个DTD或者架构文档后,有的解析器会读取DTD或架构,并据此检查XML文档的结构.如XML文档符合DTD或架构的要求,就认为XML文档是"有效的".如解析器不能根据DTD或架构来验证文档,就称为"非验证解析器".

由于XML文档内容可采用多种方式构造,所以应用程序不能确定它收到的文档数据是完整的,是丢失数据的,还是顺序正确的.DTD和架构解决了这个问题,它们提供了全面的方式来描述文档的内容.应用程序可使用一个DTD或者架构文档对文档内容执行有效性验证.

在不远的将来,架构有望全面取代DTD,成为描述XML文档结构的主要手段.

15.7 XML词汇表

MathXML 它由W3C开发,用于描述数学符号及表达式.可解析和呈现MathML的一个应用程序是W3C的Amaya浏览器/编辑器,可到以下网址免费下载:

www.w3.org/Amaya/User/BinDist.html

按书上说的可以根据XML的描述显示各种数学公式,但试了一下没成功!郁闷!不知道为啥?

CML 化学标记语言(Chemical Markup Language,CML)是用于表示分子和化学信息的XML词汇表。可.使用Jumbo浏览器来编辑和查看CML。它的网址是www.xml-cml.org.

按书上说可以根据XML的描述显示各种化学分子式,但在网上根本没有找到Jumbo浏览器,网址也打不开。

第16章 Python的XML处理

学习目标

1.用程序化的手段创建XML标记

2.用文档对象模型(DOM)处理XML文档

3.用Simple API for XML(SAX)从XML文档获取数据

4.创建一个基于XML的消息论坛

还是关于Python中包的使用



第17章 数据库应用程序编程接口(DB-API)

学习目标

1.理解关系数据库模型

2.用SQL进行基本的数据库查询

3.利用MySQLdb模块的方法在数据库中查询,插入和更新数据

第18章 进程管理

学习目标

1.理解进程记号法

2.理解如何创建和管理进程

3.学习如何在Python中执行shell命令

4.理解如何控制进程的输入和输出

5.学习发送信号和解释信号

第19章 多线程处理

学习目标

1.理解多线程处理的背景

2.理解多线程处理如何改进性能

3.理解如何创建,管理和销毁线程

4.理解线程生命周期

5.研究几个线程同步的例子

第20章 联网

学习目标

1.理解Python联网元素,即URL,套接字和数据文报

2.使用套接字和数据文报实现Python联网应用程序

3.理解如何用Python实现客户/服务器应用程序

4.理解如何创建基于网络的协作式应用程序

5.构建一个多线程服务器

第21章 安全性

学习目标

1.理解基本安全概念

2.理解公钥加密

3.了解流行安全协议,比如SSL

4.理解数字签名,数字证书,证书颁发机构和公钥基础结构

5.理解Python编程的安全性问题

6.学会编写受限Python代码

7.理解安全系统面临的各种威胁

第22章 数据结构

学习目标

1.使用自引用类和递归生成链接数据结构

2.创建和操纵动态数据结构,如链表,队列,堆栈和二叉树

3.理解链接数据的几种重要应用

4.理解如何通过合成创建可重用的数据结构

第23章 案例分析:网上书店

学习目标

1.使用Python和CGI,建立一个三层的,客户/服务器结构的,分布式的Web应用程序

2.理解HTTP会话概念

3.会用Session类在不同页之间跟踪HTTP会话

4.使用脚本创建XML,并用XSLT将XML转换成可由客户显示的格式

5.在Apache Web服务器上部署应用程序

6.扩展应用程序,使其支持无线客户端

第24章 多媒体

学习目标

1.介绍Python多媒体应用程序编程

2.学会使用PythonGL模块创建三维程序

3.用Python和Alice操纵三维对象

4.学会使用Python和pygame创建多媒体应用程序

第25章 Python服务器页

学习目标

1.会创建和部署PSP

2.会用Python和PSP的隐式对象来创建动态网页

3.理解PSP动作

4.会在XHTML嵌入Python Scriptlet

5.会用预编译指令指定全局PSP信息

6.创建一个基于XML的论坛程序
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: