python 新手入门+概括

来源:互联网 发布:迅雷看看 mac 编辑:程序博客网 时间:2024/05/21 12:55

Python新手必读(中国开源项目)

第一章    开始

为什么要选择python?
一个高层的总结
把python描述成一种面向对象的脚本语言可能是最合适的。它的设计混合了传统语言的软件工程的特点和脚本语言的易用性。它的主要特性有如下几个:
1、它是面向对象的。它的类模式支持了诸如多态,操作符重载,多重继承等高级特性。
2、它是自由的。它是开源的,像Tcl和Perl一样。
3、它是可移植的。它是用ANSI C写成的。可以在今天所用的各种平台上编译、运行。
4、它是功能强大的。python丰富的工具集使它位于传统脚本语言(如Tcl and perl)和系统语言(如C,C++,JAVA)之间。
5、它是可混合的。python程序可十分轻易地与其它语言写成的组件“粘合”在一起。如python/c集成api,
JPython。
6、它是易于使用的。开发周期短,程序大小是其它语言的几分之一。
7、它是简单易学的。

实践中的python
1、系统软件,python对操作系统的内置接口,使它成为书写可移植程序,可维护的系统管理工具的理想工具。
2、图形用户接口。它有一个叫Tkinter的TK API的标准的面向对象接口。
3、组件集成。它可被c/c++扩展和嵌入其它系统的能力。
4、快速原型。
5、Internet脚本。
6、数字编程。NumPy数字扩展程序模块包含诸多数字编程工具。
7、数据库编程。提供了与sybase,oracle,odbc等数据库接口。
8、其它的图像处理,人工智能,分布式对象等。

python与类似工具的比较
1、比Tcl强大,可用于大型系统的开发。
2、比Perl有更清晰的语法,更简单的设计,使它更可读,更容易理解。
3、不要与java比较,python只是一个脚本语言,而java and c/c++是系统语言。

如何运行python程序?
1、交互式。交互命令行,在系统下打入python,就进行交互命令模式,提示符是>>>,按Ctrl+D退出。
% python
>>>print "hello,my friend!";
hello,my friend!
2、运行模块文件。模块文件是包含python语句的简单文本文件。你可以用python xxx来运行。
用文本编辑器编写example.py的内容如下:
import sys
print sys.argv
接着就可以用以下命令运行。
% python example.py
3、运行unix类型的脚本。就像shell脚本一样。
#!/usr/local/bin/python
print "test ............"    注释以#开头。
存盘后,把它的属性改成可执行,就可以像shell脚本一样执行了。
4、嵌入的代码和对象。在c程序中可调用python的运行时API。
#include <python.h>
...
py_Initialize();
PyRun_SimpleString("x=brave +sir +robin");

初览模块文件
以.py为结尾的模块文件能导入或重载。例子:
myfile.py模块内容为
title = "the example test"
现在这个模块可能被其它程序导入,而且能访问title变量。
方法一:
import myfile
print myfile.title
方法二:
from myfile import title
print title

初览名称空间检测
另一个技巧是用内置函数dir()跟踪程序交互运行时的名字。

python设置细节
重要的环境变量
path            系统shell查找路径,用来发现python。
PYTHONPATH        Python模块查找路径,用于导入。
PYTHONSTARTUP        Python交互式启动文件路径。
TCL_LIBRARY,TK_LIBRARY    GUI扩展变量(Tkinter)

第二章    类型与操作符

Python程序结构
它可分为模块,语句和对象三部份,关系如下:
1、程序是由模块组成。
2、模块中包含语句。
3、语句生成并处理对象。

为什么要使用内置类型?
1、内置对象使简单程序写起来更容量。
2、python提供对象并支持扩展程序。
3、内置对象是扩展程序的组件。
4、内置对象总比定制的数据结构类型更加有效。

内置对象预览
Number(数字)        3.4,333,5+4j
String(字符串)        'sleep','hello'
List(列表)        [1,3[4,'this'],33]
Dictionary(字典)    {'aaa':'test','bbb':'yyy'}
Tuple(元组)        (1,'aa',4,'cc')
File(文件)        text = open('a','r').read()

数字
python支持常见的数字类型,(整数,浮点数),常量和表达式。另外还提供更高级的数字类型支持。包括复数,无限精确整数,大量的数字工具库。
正常整数(c的长整型)        1234,-11,0
长整数(无限大小)        88888888L
浮点数(c的双整型)        2.33,3.14e-10,4E21i
复数常量            3+4j,2.0+4.0j,3J

表达式操作符
x or y                逻辑或
lambda args:expression        匿名函数
x and y                逻辑与
not x                逻辑反
<,<=,>,>=,==,<>,!=        比较操作符
is,is not            身份测试
in,not in            序列成员关系测试
x | y                位或
x ^ y                位异或
x & y                位与
x<<y,x>>y            把x向左或向右移动y位
x+y,x-y                相加/合并,相减
x*y,x/y,x%y            乘/重复,除,余数/格式
-x,+x,~x            一元取反,一致,位取补
x[i],x[i:j],x.y,x(...)        索引,分片,限定,函数调用
(...),[...],{...},`...`        元组,列表,字典,转化为字符串

混合操作符,表中越往下的结合性越强

可用括号将表达式分组

在混合类型的表达式上,python先将操作对像转化为最复杂的操作类型,然后再运行同种类型的数字运算,如一个整数与一个浮点数相加,python就会把整数转化为浮点数,再把两个浮点数相加。python的数字类型复杂程序如下:整数<长整数<浮点数<复数。

数字在实际中的应用
位操作
>>>x = 1    #0001
>>>x << 2    #左移两位 0100
4
>>>x | 2    #位或:0011
3
>>>x & 1    #位与:0001
注意:x的值一直都是1,没有变化。

python提供了内置函数和内置模块用于数字处理。
>>>import math
>>math.pi
3.14159265359
>>>pow(2,4)    #内置函数,不用导入。

字符串
s1 = ''            空字符串
s2 = "spam's"        双引号,单引号无需加反斜杠转义。
block = """..."""    三引号块,字符串可跨过多行。
s1 + s2                合并
s2 * 3                重复
s2[i]                索引
s2[i:j]                分片
len(s2)                长度
"a %s parrot" % 'dead'        字符串格式
for x in s2            迭代
'm' in s2            成员关系

python不允许你在+ and *号表达式中混合数字和字符,如'abc' + 9 会出错。

索引和分片
因为字符串的定义是有序的字符集合,所以可以通过位置访问它们的内容。在python,通过索引取得字符的位移。如同C一样,偏移以0开始,以比字符长度小1的值结尾。python还可以通过负偏移从序列中取值。
>>>s = 'spam'
>>>print s[0],s[1],s[2],s[3]    #索引
s p a m
>>>print s[1:3],s[1:],s[:-1]    #分片
pa pam spa

修改和格式化
在python中改变文本信息,只需用合并,分片这样的工具建立并赋值成一个新值即可。
>>>s = s + '!'
spam!
>>>s = s[:4] + 'test'
spamtest
>>>'this is %d %s word' % (1,'good')    格式化字符串输出,类似于C的sprintf。重载了%操作符,原来的%操作符是取余。
this is 1 good word

字符串格式代码
%s    字符串
%c    字符
%d    十进制(整数)
%i    整数
%u    无符号整数
%o    八进制整数
%x    十六进制整数
%X    十六进制整数大写
%e    浮点数格式1
%E    浮点数格式2
%f    浮点数格式3
%g    浮点数格式4
%G    浮点数格式5
%%    文字%

>>> '%e %E %f %g %G' % (1.1,2.2,3.3,4.4,5.5)
'1.100000e+000 2.200000E+000 3.300000 4.4 5.5'

普通的字符串工具
python提供string这个处理字符串的工具模块。它包括转换大小写,查找子串,将字符转化成数字等功能。
>>> import string
>>> s = 'test'
>>> string.upper(s)
'TEST'
>>> string.find(a,'s')    #返回索引的子串
-1
>>> string.atoi("1234") +1234    #把字符转化为整数进行加减运算
2468
>>> 'aa'+`99`    #用``把整数转化为字符进行组合。
'aa99'

字符串常量变量
>>> a = "aa'b"
>>> print a
aa'b
>>> a = 'aa"b'
>>> print a
aa"b
>>> a = 'aa/'b'
>>> print a
aa'b
>>> a = """test
test
test
"""
>>> print a
test
test
test

字符串的反斜线字符
/newline    忽略(继续)
//        反斜杠
/'        单引号
/"        双引号
/a        响铃
/b        退格
/e        退出
/000        空
/n        新行(换行符)
/v        垂直制表符
/t        水平制表符
/r        回车
/f        进纸符
/0XX        八进制值XX
/xXX        十六进制值XX
/other        任何其它的字符

列表
列表可包含任何种类的对象:数字、字符串甚至其它列表。在python中的列表的主要属性有:
1、任意对象的有序集合。
2、通过偏移存取。和字符串一样,可分片,合并等操作。
3、可变长度,异构,任意嵌套。
4、属于序列可变的类别。可在原位上改变,支持删除,索引赋值和方法等。
5、对象引用的数组。类似于C的指针的数组。列表是C的数组,引有就像C的指针(地址)。

常用列表常量和操作
L1 = []            一个空的列表
L2 = [0,1,2,3]        四项:索引为0到3
L3 = ['a',['b','c']]    嵌套的子列表
L2[i],L3[i,j]        索引
L2[i:j]            分片
len(L2)            计算列表长度
L1 + L2            合并
L2 * 3            重复
for x in L2        迭代
3 in L2            成员关系
L2.append(4)        方法:增长
L2.sort()            排序
L2.index(1)            查找
L2.reverse()            反转
...                ...
del L2[k]        缩小
L2[i:j] = []        同上
L2[i] =1        索引赋值
L2[i:j] = [1,2,3]    分片赋值
range(4),xrange(0,4)    生成整数的列表/元组

例子:
>>> len ([1,2,3])
3
>>> [1,2,3]+[4,5,6]
[1, 2, 3, 4, 5, 6]
>>> [1,2]*4
[1, 2, 1, 2, 1, 2, 1, 2]
>>> for x in [1,2,3]:print x
1
2
3

索引和分片
>>> L = ['aa','bb','cc']
>>> print L[2]        #索引
cc
>>> print L[1:2]    #分片
['bb']


原位改变列表
>>> L = ['aa','aa','cc']    
>>> L[1] = 'bb'        #索引赋值
>>> print L
['aa', 'bb', 'cc']

>>> L = ['aa','bb','cc']
>>> L[2:3] = ['CC']    #分片赋值,删除+插入
>>> print L
['aa', 'bb', 'CC']

>>> L.append('please')        #append方法调用,其它方法类似。
>>>print L
['aa', 'bb', 'CC','please']

注意:append和sort在原位改变了关联的列表对象,但是不返回列表,它们返回一个叫None的值。对象本身同时改变,所以无需重新赋值。

字典
字典是无序的集合,和列表相对,因为列表是有序的集合。字典中的项是通过键来存取的,而不是通过偏移。(perl中的散列?)
字典的主要属性如下:
1、通过键而不是偏移量来存取。
2、无序的任意对象集合。
3、可变长度、异构、任意嵌套。
4、属于可变映射类型。对象将键映射到值。
5、对象引用表(散列表)。本质上说字典是作为散列表实现的。

常见的字典对象常量和操作
d1 = {}                空的字典
d2 = {'aa':2,'bb':4}        两项的字典
d3 = {'aa':{'bb':1,'cc':2}}    嵌套
d2['aa'],d3['aa']['cc']        通过键索引
d2.has_key('aa')        方法:成员关系测试
d2.keys()            键的列表
d2.values()            值的列表
...
len(d2)                长度(所存储的项的数目)
d2[key] = new            添加/改变
del d2[key]            删除

提示:
1、字典不是序列,所以不能像在字符串和列表中那样直接通过一个for进行迭代,需调用字典的keys方法,返回一个键值列表。
2、序列操作,像合并,分片无法操作。
3、赋值给新的索引将添加项。
4、键没有必要总是字符串。

元组(tuple)
元组由简单的对象组构成。不能原位改变。写在一串圆括号中,与列表类似。
1、任意对象的有序集合。
2、通过偏移量存取。
3、属于不可变序列类型。
4、固定长度,异常,任意嵌套。可包含列表,字典其它元组。
5、对象引用的数组。

常见的元组常量和操作
()            空元组
t1 = (0,)        只有一项的元组,不是一个表达式。不要漏了逗号。
t2 = (0,1,2,3)        四项的元组
t2 = 0,1,2,3        四项的元组,同上一行。
t3 = ('aa',('bb','cc'))    嵌套的元组
t1[i],t3[i][j]        索引
t1[i:j]            分片
len(t1)            计算长度
t1 + t2         合并
t3 * 3            重复
for x in t1        迭代
3 in t2            成员关系

有了列表,为什么还要用元组?
元组的不可变性可以提供某些整体性,你能肯定在一个程序中一个元组不会被另一个引用改变。一个来自实践的原则:列表可以用于想变动的有序集合,元组则处理其它事情。

文件
文件对象方法和C标准库的函数是一一对应的。
常见的文件操作
output = open('/temp/test','w')        生成输出文件(写方式)
input = open('data','r')        生成输入文件(读方式)
s = input.read()            把整个文件读到一个字符串中
s = input.ead(N)            读N个字节
s = input.readline()            读下一行(越过行结束标志)
L = input.readlines()            读取整个文件到一个行字符串的列表中
output.write(S)                把字符串S写入文件
output.writelnes(L)            将列表L中所有的行字符串写到文件中
output.close()                手工关闭
任何情况下,Python程序中的文本采取字符串的形式,读取一个文件将返回字符串形式的文本,并且文本作为字符串传递给write方法。调用close方法将终止对处部文件的连接。
 
实际的文件操作
>>>file = open('test','w')    #打开文件用以输入,如果文件不存则生成。
>>>file.write('hello world')    #把'hello world'写入文件
>>>file.close()            #关闭文件句柄
>>>read = open('test','r')    #打开文件用以输出
>>>read.readline()        #读一行
'hello world'
>>>read.readline()        #空字符串:到文件结尾
''

共有的对象属性
对象分类
数字        数字的        不可变
列表        序列的        可变
字符串        序列的        不可变
字典        映射的        可变
元组        序列的        不可变
文件        扩展程序    -

共性
1、列表,字典和元组可以包含任何种类的对象。
2、列表,字典和元组可以任意嵌套。
3、列表,字典可以动态扩大和缩小。

比较相等性和真值
==        测试值是否相等        
is        测试对象的一致性
>>> L1 = [1,2,'33']
>>> L2 = [1,2,'33']
>>> L1 == L2
True
>>> L1 is L2
False

真值表
"aaa"        true
""        false
[]        false
{}        false
1        true
0.0        false
None        false    #None是python中一个特列对象,总被认为是假的。

python的比较方法
1、数字通过关系值比较。
2、字符串按字典顺序,字符到字符的比较  ("abc" < "ac"),第二个位c比b大,所以为真。
3、列表和元组通过对每个内容作比较,从左到右。
4、字典通过比较排序后的(键,值)列表进行比较。


python中类型层次
数字---    整数---    整数,长整数
      |
      |---浮点数,复数


集合----序列----可变----列表
    |     |
    |     |----不可变的----字符串,元组
    |---映射----字典


可调用的-----函数-----类-----方法-------绑定(通过对象来访问方法)
                              |--------非绑定(通过类名来访问方法,并专门传递一个对象引用)


其它---模块---实例---文件---空

内部---类型---代码---框架---轨迹


内置类型常见问题
1、赋值生成引用,而不是拷贝。
>>> L = [1,2,3]
>>> M = [1,L,3]
>>> print M
[1, [1, 2, 3], 3]
>>> L[1] = 0        #也改变了M,共享引用。
>>> print M
[1, [1, 0, 3], 3]
解决办法,通过拷贝避免共享对象。
>>> L = [1,2,3]
>>> M = [1,L[:],3]    #嵌入的L拷贝
>>> print M
[1, [1, 2, 3], 3]
>>> L[1] = 0        #只改变L,M不改变。
>>> print M
[1, [1, 2, 3], 3]
>>> print L
[1, 0, 3]

同层深度的重复加
>>> L = [1,2,3]
>>> X = L * 4
>>> print X
[1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3]
>>> Y = [L] * 4
>>> print Y
[[1, 2, 3], [1, 2, 3], [1, 2, 3], [1, 2, 3]]
>>> L[1] = 0        #改变Y但不改变X
>>> print X
[1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3]
>>> print Y
[[1, 0, 3], [1, 0, 3], [1, 0, 3], [1, 0, 3]]
解决方法同上
>>> L = [1,2,3]
>>> Y = [L[:]] *4
>>> print Y
[[1, 2, 3], [1, 2, 3], [1, 2, 3], [1, 2, 3]]
>>> L[1] = 0
>>> print L
[1, 0, 3]
>>> print Y
[[1, 2, 3], [1, 2, 3], [1, 2, 3], [1, 2, 3]]

循环数据结构不能打印
>>> L = [1]
>>> L.append(L)    #追加引用到同一个对象中,在1.5.1之前这是个循环,需按ctl-c中断。
>>> print L
[1, [...]]
解决方法,不要这样做。这是一种无意义的操作。

不可变类型在原位不可以被改变
>>> T = (1,2,3)
>>> print T
(1, 2, 3)
>>> T[2] = 4

Traceback (most recent call last):
  File "<pyshell#74>", line 1, in -toplevel-
    T[2] = 4
TypeError: object doesn't support item assignment
>>> T = T[:2] + (4,)    #用分片,合并等操作生成一个新的对象。
>>> print T
(1, 2, 4)

第三章    基本语句


程序由模块组成,模块包含语句,语句生成并处理对象。

赋值
1、赋值生成对象引用,而不是对象的拷贝,因此,与数据存储结构相比,python的变量更像C中的指针。
2、名字在第一次赋值时即已生成,不用事先声明。
3、名字在引用前必须赋值。
4、隐式赋值:import,from ,def,class,for函数参数等。
赋值语句形式
a = 'test'            基本形式
a,b = '1','2'            元组赋值
[a,b] = ['test','goods']    列表赋值
a = b = 'test'            多目标赋值
a,b = b,a            交换值

变量名规则
1、与C类似,以下划线或字母开头,随之可以是任意位的字母,数字或下划线。
2、大小写敏感。
3、保留字限制。

表达式
aa(bb,cc)        函数调用
aa.read(bb)        方法调用
aa            交互式打印
aa < bb and bb!=cc    复合表达式
aa < bb < cc        范围测试

if条件测试
一般格式为:
if <条件1>:
    <语句1>
    elif <条件2>:
        <语句2>
    else:
        <语句3>
在python中没有switch and case语句,多路分支可被一系列if/elif,或是通过检索字典,查找列表代替,字典和列表可在运行时生成,比逻辑上的硬性编码更有弹性。
>>> choice = 'aa'
>>> print {'aa': 12.33,'bb':343.3,'cc':44}[choice]    #一个基于字典的'switch'语句
12.33

python的语法规则
1、语句一条接一条执行,一直到你说不为止。
2、块和语句边界自动控测。用首行缩进形式将语句分组。
3、复合语句= 首行,“:”,缩进语句。
4、空格和注释被忽略。
5、语句太长可跨行写。

真值测试
1、真代表着任意非空的数或非空的对象。
2、假代表不真,数0,空的对象或None。
3、比较或判断相等返回1或0(真或假)。
4、and 和 or布尔操作返回一个真或假的操作数对象。


while 循环
一般格式:
while <条件>:    
    <语句1>
else:
    <语句2>
例子:
while 1:
    print 'type ctrl-c to stop me'    #1为真,所以无限循环地打印。

遍历字符串:
>>> x = 'test'
>>> while x:        #只要x不为空就执行
    print x,
    x = x[1:]    #从x中取出第一个字符。

test est st t
循环计数
>>> a=0;b=10
>>> while a < b:
    print a
    a = a+1
0 1 2 3 4 5 6 7 8 9

break,continue,pass,else循环
break和continue和C类似。
break        跳出最近的包围它的循环
continue    跳到最近的循环的开头
pass        什么都不做,只是一个空的占位空语句。
else        运行并且只有在循环正常退出的情况下运行。没有碰到break。

包含break and continue的循环语句。
while <条件测试>:
    <语句>
    if <条件测试>:break    #跳出循环,忽略else。
    if <条件测试>:continue    #转到循环开头。
    else:
        <语句>        #如果没有遇上break

for循环
for <目标> in <对象>:        #该目标赋以对象的项
    <语句>            #重复循环体:使用目标
else:
    <语句>            #如果没有遇上break
当python运行for时,它将序列对象中的项一个接一个赋值给目标,并且为每一个执行一次循环体。for也支持一个可选的else块,和在while中完全一样,如果循环没有遇到break,它就会执行,也就是说序列中所有的项都被访问了。
for <目标> in <对象>:
    <语名>
    if <条件测试>:break    #跳出循环,忽略else。
    if <条件测试>:continue    #转到循环开头。
    else:
        <语句>        #如果没有遇上break

range和计数循环
range函数可能成一个连接的整数列表,它可以在for中作为索引使用。
带一个参数时,range生成一个从0开始到参数值(不包含参数)的列表。
>>> range(10)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
带两个参数时,range生成以第一个参数为下边界,第二个参数上边界的列表。
>>> range (10,20)
[10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
带三个参数时,range生成以第一个参数为下边界,第二个参数上边界,第三个参数为步长的列表。
>>> range(10,20,2)
[10, 12, 14, 16, 18]

利用循环扫描文件内容
file = open ('test','r')
while 1:
    line = file.readline()    #取得下一行
    if not line:break    #在文件结束时跳出循环
    在这里处理行
也可用for实现同样功能
file = open ('test','r')
for line in file.readlines():    #读入一个行列表
    在这里处理行

最简单的遍历一个序列的方法是用一个简单的for循环,python为你处理了大多数的细节。
>>> x = 'myfile'
>>> for a in x:
    print a
m
y
f
i
l
e
在内部,for始初化一个索引,检测序列是否结束,索引序列以取得当前的项。在每一个迭代上增加索引。如果你真想知道索引的逻辑复杂性,你可以用一个while循环做一个。这个形式和C中的for相似。
>>> x = 'myfile'
>>> i = 0
>>> while i < len(x):
    print x[i]
    i = i + 1
m
y
f
i
l
e

用for 也可以。
>>> x = 'myfile'
>>> i = 0
>>> for i in range(len(x)):
    print x[i]
m
y
f
i
l
e

python代码编写中的常见问题
1、不要忘了冒号。
2、一定要从第一列开始写顶层。
3、交互提示符下的空白行代表结束语句。
4、缩进一致性,不能混合使用制表符和空格。
5、在python中不要写c/c++代码。没有必要在if的条件和while的头加上括号。
6、不要总想得到结果。list.append(),list.sort()不返回值,无需赋值就可以调用它,不要写成sort = list.sort()
7、适当地使用call and import。

第四章    函数

函数两个主要作用是:
1、代码重用
2、过程的分解

函数的基础
1、def生成一个函数对象并赋给它一个名字
2、return给调用者返回一个结果对象。
3、global声明模块级被赋值的变量。
4、参数通过赋值传递(对象引用)。
5、参数,返回类型和变量不用声明。

def <名字> (arg1,arg2,....,argN):
    <名字>
return <值>
没有return的函数自动返回一个None。

>>> def time(x,y):
    return x*y
>>>time(2,3)
6
>>>time('test',3)    #函数是无类型的
testtesttest

函数中的作用域规则
通常函数定义一个局部作用域,模块定义一个全局作用域。关系如下:
1、模块是一个全局作用域
2、对函数的每个调用是一个新的局部作用域。
3、赋值的名字是局部的,除非声明是全局。
4、所有其它名字都是全局的或内置的。

名字解析LGB规则
1、大多数名字引用在三个作用域中查找:先局部(Local),次之全局(Global),再次之内置(Build-in)。
2、名字赋值默认情况下生成、改变局部的名字。
3、'global'声明把赋值的名字映射到一个包含它的模块的作用域中。

global语句
它就象一个声明,告诉python,一个函数计划改变全局名字---包围它的模块的作用域内的名字。

参数传递
1、参数通过局部名字传递。
2、在一个函数中对参数名赋值不影响调用者。
3、在一个函数中改变一个可变的对象参数可能影响调用者。
>>> def changer(x,y):
    x = 2        #只改变局部的名字值
    y[0] = 'test'    #在该位置改变共享的对象,y传递一个可变对象,对在函数中对y[0]的赋值的结果影响了函数返回后L的值。
    
>>> x = 1
>>> L = [1,2]
>>> changer(x,L)    #x 没变,L改变了
>>> x,L
(1, ['test', 2])

python通过赋值传递参数的方式,与C++中的参数引用不同,但与C的类似:
1、不可变参数作用类似于C中的“传值”模式。
2、可变参数作用类似于C的“传指针”模式。

特列参数匹配模式
位置        从左到右
关键字        通过参数名匹配
可变参数    捕捉未匹配位置或关键字参数

func (value)        正常参数:通过位置匹配
func (name = value)    关键字参数,通过名字匹配
def func (name)        正常参数:匹配任何位置和名字
def func (name = value)    默认的参数值,如果没有在调用中传递的话。
def func (*name)    匹配剩下的位置变量(在一个元组中)
def func (**name)    匹配剩下的关键字变量(在一个字典中)
规则:
1、在调用中,关键字参数必须出现在所有非关键字参数后。
2、在一个函数首部,*name必须在普通参数和默认后,**name必须在最后。
python内部在赋值前采取下列步骤匹配参数:
1、通过位置赋值非关键字参数。
2、通过匹配名字赋值关键字参数。
3、赋值额外的非关键字参数给“*name”元组。
4、赋值额外的关键字参数给“**name”字典。
5、在首部给无赋值的参数赋以默认值。

其它内容
lambda表达式
除了def语句,python还提供了一个可以生成函数对象的表达式。因为它与LIST语言中的一个工具类似,所以叫lambda,lambda是一个表达式,而不是一个语句;它的结构体是一个单一的表达式,不是一个语句块。格式如下:
lambda 参数1,参数2...参数N:使用参数的表达式。
如用def写一个函数:
def func (x,y):return x+y
func(1,2)
3
可以用lambda写成:
f = lambda x,y: x +y
f(1,2)
3

可以在一个列表常量中嵌入lamdba表达式,建立一个函数列表:
L = [lambda x:x**2,lambda x:x**3,lambda x:x**4]
for f in L:
    print f(2)    #打印4,8,16
print L[0](30)        #打印9

内置的apply函数
有的程序需要调用任意的函数,而无须事先知道它们的名字或参数。内置函数可以做到这一点:
>>>apply (func,(1,2,3))
apply函数简单的调用传递的参数,用函数所需的参数匹配传递的参数。它的一个优点是,它无须知道在一个函数中有多少个参数被调用。

内置函数map
程序通常可以做的一件事是:对列表中的每一个成员进行一个操作并收集结果。例如:更新一个列表中的所有数据,可以用一个for循环轻松实现:
>>> counts = [1,2,3,4]
>>> updated = []
>>> for x in counts:
    updated.append(x + 10)
>>> updated
[11, 12, 13, 14]
由于这个操用很常见,所以python提供了一个内置工具map函数来完成这个任务,map函数对在一个常列对象中的每一项都调用了一个传递的函数,并返回一个包含所有调用结果的列表。
>>>def inc (x): return x + 10
>>>map(inc,counts)
[11,12,13,14]

python的过程
在python中return是可选的,所以不带return的函数就与其它语言中的过程等效。

函数设计概念
1、输入用参数,输出用return语句。
2、只在绝对必要时才用全局变量。全局变量通常是对函数通信的一种很不好的工具。
3、不要改变参数除非调用者期望这样做。

函数是对象:非直接调用
因为函数在运行时是对象,可以写程序来处理它们。函数对象可以被赋值,传递给其它函数,在数据结构中存储等。
>>> def echo(test):
    print test
>>> echo('aa')
aa
>>> x = echo        #用x引用函数对象
>>> x('hello')        #给函数赋值
hello

函数的常见问题
局部名字静态检测
默认情况下,python把函数中赋值的名字归类为局部的。局域作用域探测是在python编译代码时检测的,而不是通过它们在运行时的赋值。
>>> x = 1
>>> def selector():
    print x        #x在一个全局作用域被发现
>>>selector()        #x被解析为外部的x。
99

如果在引用后对x赋值,为发生什么?
>>> def selector():
    print x        #x还没存在
    x =2        
>>> selector()        #提示出错,得一个未定义的名字错误。

Traceback (most recent call last):
  File "<pyshell#55>", line 1, in -toplevel-
    selector()
  File "<pyshell#54>", line 2, in selector
    print x
UnboundLocalError: local variable 'x' referenced before assignment

解决办法
如果想打印全局变量x,应该在一个global语句中声明它。

嵌套的函数不是嵌套的作用域,不要指望作用域在python中嵌套。

第五章    模块


这一章介绍python的模块---最高级的程序组织单位。
import        允许客户按整体取得一个模块
from        允许客户从一个模块中取得某些特定的名字
reload        提供了一种无需停止python就可以重载模块代码的方法

为什么要使用模块
1、代码重用。
2、系统名字空间的划分。是组织系统组件的工具。
3、实现服务或数据的共享。只要一个模块,就可以被多个客户导入。

模块基础
生成模块的形式:python文件,C扩展程序,很多python的内置工具事实上都是导入的C扩展模块。
使用模块:import,from,reload()
模块查找路径:PYTHONPATH

定义
模块文件以.py后缀结尾,文件名不要与保留字重名。

用法
import 模块名
from 模块名 import xxx
from 模块名 import *

模块文件就是名字空间
1、模块语句在第一次导入时执行
2、顶层赋值生成模块的属性,在导入过程中,在文件顶层赋值名字的语句(=,def)生成模块对象的属性,赋值的名字在模块的名字空间存储
3、模块的名字空间:可用__dict__,or dir()访问。
4、模块文件是单一作用域的(局部的就是全局的)。

名字限定
简单变量        x代表在当前作用域中查找名字。
限定            x.y代表在x对象中查找y属性。
限定路径        x.y.z代表在对象x中查找名字y,再在对象x.y中查找z。
一般性            限定可以对所有拥有属性的对象工作:模块,类,C类型等。

导入模式
导入只发生一次。模块在第一次import或from的时候载入运行,默认情况下,每个过程python只执行一次。可用以初始化变量。

import或from都是赋值
1、import把整个模块对象赋值给一个名字。
2、from把一个或多个名字赋值给另一个模块中的同名字对象。

重载模块
使用reload()函数强迫一个已经载入的模块代码重新载入。

模块编译模式
与 java相同,python程序被编译为一种称之为字节码的中间形式。它在一个虚拟机的东西上运行。python在模块第一次导入时自动把它们编译成字节码,而且,它保存在一个文件中,以.pyc为后缀。如果.py源文件更改,python会智能化地在导入时重新编译。编译过和.pyc文件是一种可以不用源代码发放系统的方法。由于python的字节码是可移植的,你通常可以在多平台上执行.pyc文件。也可以把python程序变为C语言的可执行形式,用标准的freeze工具打包字节码就可生成一个C程序。

__name__ 和__main__
1、如果文件作为程序运行,在启动时,__name__设定为字符串__main__。
2、如果文件是被导入的,__name__被设为用户已知的模块名。
结果,模块可以检测自已的__name__,决定是运行还是被导入。

第六章    类


类是python面向对象编程的主要工具,它是可选的。

为什么要使用类
继承(inheritance),一次编程,多次重复作用。
合成(composition),协调各部份工作。

三个关键特征:
1、多个实例,类是一个产生一个或多个实例的模板,每次调用一个类,就产生一个具有不同名字空间的对象,每个由类产生的对象可以访问类的属性,但有各自不同的存放数据的名字空间。
2、通过继承来定制。通过覆盖(override)它们的属性来扩展。通过继承可以定义名字空间的层次。
3、操作符重载。通过提供特列的协议方法,对内置类型适用的操作符也适用于类定义的对象,例如可以对用户自定义的对象使用分片,合并,索引等操作。

类的基础知识
1、class语句创建一个类对象并赋给它一个名字。
2、class语句内部的赋值生成类的属性。
3、象调用函数一样调用类就生成一个新实例对象。
4、每个实例对象都继承了类的属性,并有自已的名字空间。
5、方法中对self的赋值就生成了实例的属性。在类的方法中,第一个参数,按贯例称为self引用的是要处理的实例对象,对self的属性的赋值,创建或改变的是实例中的数据,而不是类的数据。
一个例子:
>>> class firstclass:            #定义一个类对象
    def setdata(self,value):    #定义类方法
        self.data = value    #self就是实例
    def display(self):
        print self.data        #self.data:每个实例的数据
>>>x = firstclass()            #生成实例
>>>x.setdata('class test')        #调用方法,self是x。x是没有自已的setdata,它会沿链接到类里找。这就是继承的运行机制。
>>>x.display()                #调用方法。                
class test

通过继承来定制类
与模块不同,类可以产生新部件(子类,subclass)而不必影响已存在的部分,这使我们可以创建一个类层次,较低的类通过覆盖属性而获得特定的行为,这通常被称为框架(framework)。这个机制背后的恩想是:
1、超类列在类首部的括号里,如class secondclass(firstclass)。
2、类从超类继承属性。
3、实例从所有相关类中继承,包括超类。
4、通过子类改变逻辑,而不是直接改变超类。在子类中覆盖超类里的名字,子类就覆盖了继承的行为。

一个例子:
>>> class secondclass(firstclass):    #继承了setdata
    def display(self):        #改变了display
        print 'current value = %s' %self.data
>>> z =secondclass()
>>> z.setdata(11)
>>> z.display()                #新的display语句
current value = 11

类可以重载python的操作符
操作符重载使我们的对象与内置的一样。__X__的名字的方法是特殊的挂钩(hook),python通过这种特殊的命名来拦截操作符,以实现重载。 python在计算操作符时会自动调用这样的方法,例如:如果对象继承了__add__方法,当它出现在+表达式中时会调用这个方法。通过重载,用户定义的对象就像内置的一样。

一个例子:
>>> class thirdclass(secoendclass):
    def __init__(self,value):        #当创建新的实例时调用,self就是新的thirdclass对象。
        self.data = value
    def __add__(self,other):
        return thirdclass(self.data + other)    #当self + other时
    def __mul__(self,other):
        self.data = self.data * other        #当self * other时
>>> a = thirdclass("abc")    #调用新的__init__
>>> a.display()            #继承的方法
Current value = "abc"
>>> b = a + 'xyz'        #调用新的__add__:产生一个新的实例
>>> b.display()
Current value = 'abcxyz'
>>> a * 3    #调用新的__mul__:改变实例本身
>>> a.display()
Current value = 'abcabcabc'

使用class语句
一般形式:
class <name>(superclass,...):        #以name命令类,superclass为需继承的超级类。
    data = value            #共享的类数据
    def method(self,...):        #方法
        self.member = value    #实例的数据
在class语句中,用特殊的命名方法重载操作符。如__init__,__add__等。

使用类的方法
方法是嵌套在class语句里的def语句创建的函数对象。抽象地看,方法描述了实例的行为。从程序的角度看,方法与普通函数的工作机制是一样的,只有一点重要区别,方法的第一个参数总是一个实例对象,也就是调用方法的主体,python自动地把对实例的方法调用转换为对类的方法调用:
insance.method(args...) ==== 转变成了==== class.methed(instance,args...)
方法中的特殊的第一个参数按贯例称为self。它很像C++中的this指针。
例子:
class nextclass:
    def printer(self,text)    #定义方法
        print text

>>> x = nextclass()        #生成实例
>>> x.printer('hello world')    #调用它的方法
hello world
当像这样通过限定实例来调用时,printer的self参数自动地被赋予实例对象(x),而字符串“hello world”传给text参数。在printer内self可以访问和设置每个实例的数据,因为它引用的正是处理的实例。我们也可以通过类来调用 printer,显式地把实例传给self参数:
>>> nextclass.printer(x,'hello world')    #class method
hello world

在类中重载操作符
1、操作符重载使得类能拦截标准的python操作。
2、类可以重载所有的python的表达式操作符。
3、类可以重载对象操作:print,函数调用,限定等。
4、重载使得类的实例看起来更像内置的。
5、重载是通过特殊命名的类方法来实现的。
方法名        重载的操作说明        调用表达式
__init__    构造函数        创建对象:class()
__del__        析构函数        释放对象的时候
__add__        “+”            x + y
__or__        “|”            x | y
__repr__    打印,转换        print x, `x`
__call__    函数调用        X()
__getattr__    属性引用        x.undefined
__getitem__    索引            x[key],for循环,in测试
__setitem__    索引赋值        x[key] = value
__getslice__    分片            x[low:high]
__len__        长度            len(x)
__cmp__        比较            x == Y ,x < y
__radd__    右边的操作符"+"        非实例 + x

例子:
__getitem__拦截了所有的索引操作
>>> class indexer:
    def __getitem__(self,index):
        return index ** 2
>>> x = indexer()
>>> for i in range(5):
    print x[i]    #x[i]将调用__getitem__(x,i)
0
1
4
9
16

用类来设计
该部份内容较难,需要一定的面向对象编程知识,暂时不细看。

第七章    异常


try    捕获由Python或程序本身引发的异常
raise    手工地引发一个异常

为什么要使用异常
1、错误处理,当python检查以程序运行时的错误就引发异常,你可以在程序里捕捉和处理这些错误,或者忽略它们。
2、事件通知,异常也可以作为某种条件的信号,而不需要在程序里传送结果标志或显式地测试它们。
3、特殊情形处理,有时有些情况是很少发生的,把相应的处理代码改为异常处理会更好一些。
4、奇特的控制流,异常是一个高层次的"goto",可以把它作为实现奇特的控制流的基础。如反向跟踪等。

异常的基础知识
python的try语句有两种风格---一种是处理异常(try/except/else),一种是无论是否发生异常都将执行最后的代码(try/finally)。


try/except/else风格
try:
    <语句>        #运行别的代码
except <名字>:        
    <语句>        #如果在try部份引发了'name'异常
except <名字>,<数据>:
    <语句>        #如果引发了'name'异常,获得附加的数据
else:
    <语句>        #如果没有异常发生
try的工作原理是,当开始一个try语句后,python就在当前程序的上下文中作标记,这样当异常出现时就可以回到这里,try子句先执行,接下来会发生什么依赖于执行时是否出现异常。
1、如果当try后的语句执行时发生异常,python就跳回到try并执行第一个匹配该异常的except子句,异常处理完毕,控制流就通过整个try语句(除非在处理异常时又引发新的异常)。
2、如果在try后的语句里发生了异常,却没有匹配的except子句,异常将被递交到上层的try,或者到程序的最上层(这样将结束程序,并打印缺省的出错信息)。
3、如果在try子句执行时没有发生异常,python将执行else语句后的语句(如果有else的话),然后控制流通过整个try语句。

try/finally风格
try:
    <语句>
finally:
    <语句>    #退出try时总会执行
raise
python总会执行finally子句,无论try子句执行时是否发一异常。
1、如果没有发生异常,python运行try子句,然后是finally子句,然后继续。
2、如果在try子句发生了异常,python就会回来执行finally子句,然后把异常递交给上层try,控制流不会通过整个try语句。
当你想无论是否发生异常都确保执行某些代码时,try/finally是有用的。

raise
要引发异常,你需要写raise语句,它的形式很简单,raise后面跟着要引发的异常。
raise <name>    #手工地引发异常
raise <name>,<data>    #传递一个附加的数据
什么是异常名(name)呢?它也许是内置作用域内的内置异常(如IndexError),或者是你程序中的任意字符串对象。

第一个例子:
缺省行为:显示错误信息。
$ python test.py
Traceback (innermost last):
  File "test.py", line 3, in ?
    a = 1 /0
ZeroDivisionError: integer division or modulo
当一个未捕获的异常发生时,python将结束程序并打印一个堆栈跟踪信息,以及异常名和附加信息。

用try捕获内置异常
如果你不想在异常发生时结束你的程序,只需在try里捕获它。
#!/usr/bin/python
try:
        a = 1 /0
        print a
except:
        print 'i get the error'
当程序运行是会捕获一个错误并执行except后面的代码。

异常的惯用法
异常并不总是坏事情,例如,文件对象的read方法在文件尾时返回一个空串,python也提供一个内置函数raw_input,它从标准输入流读入。与read方法不同,当遇到文件尾时,raw_input()引发内置的EOFError错误。所以可以这样用:
while 1:
    try:
        line = raw_input()        #从stdin读入行
    except EOFError:
        break                #在文件末尾退出循环
    esle:
    其它处理代码

用异常传递成功的信号
Found = 'item found'
def search():
    引发或返回Found
try:
    search()
except Found:
    successful
else:
    fail

可以使用try来调试代码,你可以用自已的异常处理替换python缺省的异常处理。把整个程序封装在一个外部try里面,你可以捕获运行时的任何异常。

异常捕获模式
try语句子句形式表
except:            捕获所有异常
except name:        只捕获特定的异常
except name,value:    捕获异常和它的附加数据
except (name1,name2):    捕获任何列出的异常
else:            如果没有异常
finally:        总是执行

捕获多个异常中的一个,python从上到下地查看except子句,括号里列出多个异常与列出单独的异常是一样的,只是更简洁一些。

运行时嵌套的异常,python会匹配最近的except。

finally子句无论如何都会执行,所以它是做清除动作的好地方,如关闭一个文件的操作。

第八章    内置工具


内置函数
可查相关资料获得
库模块
可查相关资料获得

第九章    用python完成常见的任务


数据结构操作
内嵌(inline)拷贝
由于python引用和管理模式,语句a = b 并没有对b引用的对象作拷贝,而只是对那个对象产生了新的引用。有时需要对一个对象的新的拷贝,而不是共享一个引用。如果要拷贝,可以用:
newlist = mylist[:]。可以理解为“从开始到结尾的分片”。
newDict = myDict.copy()        #python1.5引入的新功能
oneDict.update(otherDict)    #用另外一个字典的内容替换

拷贝:copy模块
[:]和.copy适用于90%的情况,如果拷贝对象是可变的话,就需要用到deepcopy深度拷贝功能。

文件操作
sys.stdin,sys.stdout,sys.stderr分别代表标准输入,标准输出和标准错误。

算出通过“管道”输入的文件行数
import
data = sys.stdin.readlines()
print "counted",len(data),"lines."
在unix下可以做如下测试:
# cat countlines.py | python countlines.py
Counted 3 lines.

寻找所有以#开始的行
import sys
for line in sys.stdin.readlines():
    if line[0] == '#':
        print line,    #注意这个逗号是需要的,因为line字符串里已经有一个换行符。

取出一个文件的第四列(这里的列是由空白符定义的)
import sys,string
for line in sys.stdin.readlines():
    words = string.split(line)
    if len(words) >= 4:
        print words[3]

取出文件的第四列,列由冒号分开,并用小写输出
import sys,string
for line in sys.stdin.readlines():
    words = string.split(line,':')
    if len(words) >= 4:
        print string.lower(words[3])

打印头10行,最后10行,并隔行输出
import sys,string
lines = sys.stdin.readlines()
sys.stdout.writelines(lines[:10])
sys.stdout.writelines(lines[-10:])
for lineIndex in range(0,len(lines),2):
    sys.stdout.write(lines[linesIndex])

计算单词'python'在文件里出现的次数
import string
text = open(fname).read()
print string.count(text,'python')

把一个文件的列变换成一个列表的行,任务是转置一个文件。
import sys,string
lines = sys.stdin.readlines()
wordlists = []
for line in lines:
    words = string.split(line)
    wordlists.append(words)
for row in range(len(wordlists[0])):
    for col in range(len(wordlists)):
        print wordlists[col][row] + '/t',
        print

逐字地读入
while 1:
    next = sys.stdin.read(1)    #读入一个单字符串
    if not next:            #或者读到EOF时是空串
        break
        处理字符串'next'

逐行地读入
while 1:
    next = sys.stdin.readline()    #读入一个单行字符串
    if not next :
        break
        处理行'next'

处理命令行上指定的一组文件,用sys模块的argv属性

处理一个或多个文件的每一行:fileinput模块

匹配一组文件:glob模块

使用临时文件,tempfile模块的mktemp(),TemporaryFile()函数。

操用程序,调用系统和功能。os.popen以一个shell命令字符串作为参数,并返回一个链接到标准输入或标准输出的文件对象。string.find在一个字符串里从左到右地找一个子串,并返回一个位置索引。

python提供了大量internet的工具使我们可以简单地操作web.

查看评论

  暂无评论
原创粉丝点击