Python系列教材第一集
Python 新员工教材
楚广明2012
借用了一些闫小勇\郑纳智同志的文档,向同志们致敬!
目录
一、 Python概述. 5
1) 第一个Python程序. 6
1. 为什么要学习Python 7
2. 代码块与缩进的差异. 8
3. 语句结尾的差异. 8
4. 注释方法. 8
5. 入口方法. 8
6. import与using语句. 8
2) 小结. 9
二、 基本数据类型. 9
1) 第一个程序的解析. 9
2) 变量的命名规范. 11
3) 空类型. 11
4) 布尔类型. 11
5) 数值类型. 12
6) 字符串类型. 12
7) 全局变量. 14
三、 基本数据类型-列表(list【】) 14
四、 基本数据类型-字典(dict{}) 16
五、 基本数据类型-元组(tuple()) 18
六、 基本数据类型-集合(set) 20
七、 运算符、表达式和流程控制. 21
1) 算术运算符与算术表达式. 21
2) 赋值运算符与赋值表达式. 22
3) 关系运算符与关系表达式. 22
八、 流程控制. 23
1) 条件语句. 23
2) 循环. 23
九、 异常. 25
十、 动态表达式. 25
十一、 函数及函数编程. 26
1) 函数的定义. 26
2) 定义一个交换函数. 27
3) 函数的默认参数与返回值. 27
4) 返回多个值. 28
5) locals函数和globals函数介绍. 28
十二、 类及面向对象. 29
1) 类的定义. 29
2) 为类添加数据. 29
3) 构造函数. 30
4) 静态成员与私有成员. 30
5) 为类添加方法. 31
6) 静态方法. 32
7) 单继承. 32
十三、 模块与包. 33
1) 对于模块的理解. 34
2) 模块的显要特性:属性. 34
3) 模块创建过程的例子. 35
4) 模块的导入. 35
5) 模块的属性. 36
十四、 字符串与简单的正则表达式. 36
1) 解决中文字符的问题. 37
2) 字符串的格式化. 38
3) 字符串的合并与分割. 39
十五、 文件IO 41
1) 基本文件功能演示. 41
2) 文件的写入. 43
3) 文件的删除与复制. 44
4) 文件与目录的重命名. 44
5) 文件内容的查找和替换. 45
6) 文件的比较. 46
十六、 Web.Py框架概述. 46
1) Python下web开发框架的选择. 46
1. Django 46
2. Pylons & TurboGears & repoze.bfg 48
3. Tornado & web.py 48
4. Bottle & Flask 49
5. Quixote 50
6. 其它(web2py、uliweb、Karrigell、Werkzeug …). 50
7. 最后关于框架选择的误区. 50
2) web.py安装. 50
3) web.py下常用框架简介. 51
4) 最简单的HelloWorld! 51
5) Web.py基本使用模板使用. 51
6) 进阶模板使用. 53
1. server2.py 53
2. post.html 53
7) URL控制. 54
1. 问题: 54
2. 解决: 54
3. 路径匹配. 54
8) 一个完整的小例子. 54
9) web.seeother 和 web.redirect转向. 55
1. 问题. 55
2. 解法. 55
3. 区别. 55
10) 包含应用. 56
1. 实现. 56
11) 使用XML 56
1. 问题. 56
2. 解法. 57
12) 获取POST数据. 57
1. login.html模板. 58
2. 主程序. 58
13) 获取客户端信息. 59
1. 问题. 59
2. 解法. 59
3. 例子. 59
4. 'ctx'中的数据成员. 59
14) 文件上传. 60
1. 简单的文件上传. 60
2. 基于新浪云的上传. 61
十七、 Web.py使用Session 62
1) 问题. 62
2) 解法. 62
3) 在template下使用Session 64
1. 问题: 64
2. 解决: 64
4) 如何操作Cookies 65
1. 问题. 65
2. 解法. 65
3. 设置Cookies 65
4. 获得Cookies 66
5) 布局模板. 67
1. 问题. 67
2. 方法. 67
3. Tip: 在布局文件(layout.html)中定义的页面标题变量. 68
4. Tip: 在其他模板中引用css文件,如下: 68
十八、 Web.py支持的语法模板. 69
1) 使用Templetor模板语法. 69
1. Introduction 69
2. 使用模板系统. 69
3. 表达式用法. 70
4. 赋值. 71
5. 过滤. 72
6. 新起一行用法. 72
7. 转义 $ 72
8. 注释. 72
9. 控制结构. 72
10. 使用 def 73
11. 使用 var 74
12. 内置 和 全局. 74
2) 使用Jinja2模板语法. 76
1. 上手的一个小例子. 76
十九、 Web.py中使用数据库. 77
1) 使用web.py自带的DB封装库. 77
1. 一个简单的数据库访问测试. 77
2. 一个复杂一点的例子. 77
3. 更加复杂的例子. 78
二十、 使用Sqlalchemy 80
1) 简介. 80
2) 初始化Sqlite数据库. 82
3) 插入数据库. 83
4) 在视图中使用sqlalchemy 86
1. 首先创建数据库models.py 86
2. 使用app.py 87
二十一、 Json的使用. 88
二十二、 Urllib模块. 89
二十三、 SQlite模块. 90
1) 简单的介绍. 90
2) 安装与使用. 90
3) 一个简单的例子. 92
4) 中文处理. 94
一、 Python概述
Python是一门优雅而健壮的编程语言,它继承了传统编译语言的强大性与通用性,同时也借鉴了简单的脚本和解释语言的易用性。它可以帮你完成工作,而且一段时间之后,你还能看明白自己写的这段代码。你会对自己如此快地学会它和它强大的功能感到十分的惊讶,更不用提你已经完成了工作了,只有你想不到,没有Python做不到的。
就算你的项目中有大量的Python代码,你也依旧可以有条不紊地通过将其分离为多个文件或模块加以组织管理。而且你可以从一个模块中选取代码,而从另一个模块中读取属性。更棒的是,对于所有模块,Python的访问语法都是相同的。不管这个模块是Python标准库中的还是你一分钟前创建的,哪怕是你用其他语言写的扩展都没有问题!借助这些特点,你会自已根据需要扩展了这门语言,而且你也这么做了。
代码中的瓶颈可能是在性能分析中总排在前面的那些热门或者一些特别强调性能的地方,可以作为Python扩展用C重写。需要重申的是,这些接口和纯Python模块的接口是一模一样的,乃至代码和对象的访问方法也如出一辙的,唯一不同的是,这些代码为性能带来了显著的提升,我们可以利用PyRex这样的工具允计C和Python混合编程,使编写扩展轻而易举,因为它会把所有的代码都转换成C语言代码。
因为Python的标准实现是使用C语言完成的(也就是CPython),所以要使用C和C++编写Python扩展。Python的java实现被称为Jython,要使用java编写其扩展。最后还有IronPython这是针对.net平台的实现。
在各种不同的系统上你都可以看到Python的身影,因为Python是用C写的,又由于C的可移植性,使得Python可以运行在任何带有ANSI C编译平台上。
l 内置的数据类型
Python提供了一些内置的数据结构,这些数据结构实现了类似Java中集合类的功能,Python的数据结构包括元组、列表、字典等 。内置的数据结构简化了程序的设计。元组相当于“只读”的数组,列表可以作为可变长度的数组使用,字典相当于java中的HashTable类型。
l 健壮性
Python提供了异常处理机制,能捕获程序的异常情况。此外,Python的堆栈跟踪对象能够指出程序出错的位置和出错的原因。异常机制能够避免不安全退出的情况,同时能帮助程序员调试程序。
l 跨平台性
Python会先编译与平台相关的二进制代码,然后再解释执行,这种方式和Java相似。Python可以运行在Windows/Linux/MAC/Unix上
l 可扩展性
Python是采用C开发的语言,因此可以使用C扩展Python,可以给Python添加新的模块、新的类。
l 动态性
Python与Javascript、PHP、Perl等语言类似。Python不需要声明变量,直接赋予值可创建一个新的变量。
l 强类型语言
Python的变量创建后会对应一种数据类型,Python会根据赋值表达式的内容决定变量的数据类型。Python在内部建立了管理这些变量的机制,出现在同一个表达式中的不同类型的变量需要做类型转换。
l 应用广泛
Python语言应用于数据库、网络、图形图像、数学计算、WEB开发、操作系统扩展等领域。Python有许多第三方库的支持。例如,PIL库用于图像处理、NumPy库用于数据计算、WxPython用于GUI库的设计、Django库用于WEB应用程序的开发等
1) 第一个Python程序
在Python的官方网站可以下载到Windows下的安装包,按照提示一路下去就可以了,记得要将Python所在的目录加入到系统Path变量中。
Python的安装包自带了一个简单的集成开发环境IDIE,你也可以选一个自己喜欢的IDE,我个人推荐PythonWin,它的语法提示功能不错,适合初学者使用。
现在你可以打开IDIE新建一个py为扩展名的Python脚本文件,输入以下内容:
保存并运行它,如果输出>>>Hello ,World!,这说明你已经成功编写了第一个Python程序,恭喜你!为了比较Python与Java编码风格等方面的差异,下边给出一个稍微复杂些的”Hello world”程序以及它的Java对照版本。
请注意第一行代码是为了支持中文,没有这一行代码的话,我们在下面如果输出中文就会出错的。
Java的实现
/**
* @author ChuguangMing
*
*/
public class myfirstjava
{
public static void main(String[] args)
{
System.out.println("这是Java的第一个程序");
}
}
Python的实现
#-*-coding:utf-8-*-
"""
我的第一个应用程序
"""
import sys
def Main():
sys.stdout.write("Hello World我的第一个程序\n")
#下面的语句看起来比较奇怪,一会儿我们会解析它
if __name__=="__main__":
Main()
1. 为什么要学习Python
我学习过很多语言,C#、Java、C/C++、PHP,但是效高即高而且简单易懂的也就数Python了,可以说它是一种胶水语言,我们可以通过它将许多语言整合在一起使用。
我们来看一段代码:
#-*-coding:utf-8-*-
"""
my fist App
"""
import sys
import urllib
def Main():
htmlresult=urllib.urlopen("http://www.baidu.com").read()
print htmlresult
#this is test
if __name__=="__main__":
Main()
2. 代码块与缩进的差异
Java使用C/C++风格的编码形式,除了要求用{}组织代码块外,语句间的缩进可以是任意的。
Python强制所有程序都有相同的编码风格,它通过缩进来组织代码块,缩进相同的语句被认为是处于同一个代码块中,在if/else等语句及函数定义式末尾会有一个冒号,指示代码块的开始。Python这种强制缩进的做法可以省去{}或者begin/end等,使程序的结构更为清晰(有的人认为恰好相反),同时也减少了无效的代码行数。
此外需要注意,尽量使用4个空格作为Python代码的一个缩进单位,最好不要使有TAB,更不要混用Tab和空格,这也算是Python的一个非强制性约定吧。
3. 语句结尾的差异
Java用分号结尾,Python不用任何符号(类似BASIC)。实际上Python也可以使用分号结尾,像这样a=1;b=2;c=3;print a,b,c不过Python中这种风格多用于调试,应为你可以很容易注释掉这一行就删除了所有的调试代码。
另外,当一行很长时,Python可以用\符号折行显示代码。
4. 注释方法
java//用单行注释,用/**/进行多行注释,而Python用#符号进行单行注释,用三引号(可单可双)进行多行注释。
java的条件表达式必须要加括号,而Python的条件表达式加不加括号均可。
5. 入口方法
java语言必须要有入口方法Main(),这是程序开始执行的地方。Python语言中没有入口方法(函数),作为解释型的语言,Python代码会自动从头执行。
如果你对这点不习惯,可以使用Python代码的内置属性__name__此属性会根据Python代码的运行条件变化:当Python代码以单个文件运行时,__name__便等于__main__,当你以模块形式导入使用Python代码时,__name__属性便是这个模块的名字。
当然,Python中的__name__属于并不是为了照顾C/C++/C#程序员的编程习惯而准备的,它主要目的是用于模块测试。想像一下在C#中编写一个组件或类代码时,一般还得同时编写一个调用程序来测试它。而Python中可以把二者合二为一,这就是__name__属性的真正作用。
6. import与using语句
在用Python写代码时,我们首先import sys,这是导入了Python的sys模块,然后在代码里我们可以引用sys模块中的对象stdout及它的write方法。在Python中这是必须的,否则你无法调用sys模块中的任何东西。
简单的说,Python中的import相当于java中的包引用。最后import可以出现在代码的任何位置,只要在引用它之前出现就可以了,不过为了提高程序可读性,建议还是在所有代码开头书写import
2) 小结
1、 Python使用强制缩进的编码风格,并以此组织代码块
2、 Python语句结尾不用分号
3、 Python标明注释用#(单行)或三引号(多行)
4、 Python语言没有入口方法(Main),代码会从头到尾顺序执行
5、 Python用import引用所需要的模块
二、 基本数据类型
1) 第一个程序的解析
“一切数据是对象,一切命名是引用”
如果你能理解这句话,说明对Python的变量与数据类型已经有了不错的认识,与Java不同,Python在使用变量之前无须定义它的类型,试着运行下面的例子:
#-*-coding:utf-8-*-
"""
我的第一个应用程序
"""
import sys
def Main():
sys.stdout.write("开始程序")
i=1
print i
#下面的语句看起来比较奇怪,一会儿我们会解析它
if __name__=="__main__":
Main()
从上边我们可以看到,变量i在使用前并不需要定义,但是必须声明以及初始化该变量。试着运行下面的例子:
i=1
print i+j
上面的代码会产生一个异常:”NameError:name ‘h’ is not defined”,Python提示变量j没有定义。这点和BASIC等弱类型的语言不一样。
另一方面,Python与java有一个很大的差异就是在程序运行过程中,同一变量名可以(在不同阶段)代表不同类型的数据,看看下面的例子:
#-*-coding:utf-8-*-
"""
我的第一个应用程序
"""
import sys
def Main():
sys.stdout.write("开始程序\n")
i=1
print i,type(i),id(i)
i=1000000000
print i,type(i),id(i)
i=1.1
print i,type(i),id(i)
#下面的语句看起来比较奇怪,一会儿我们会解析它
if __name__=="__main__":
Main()
变量i的类型在程序执行过程中分别经历了int long float的变化,这和静态类型语言如C语言有很大不同。静态语言只要有一个变量获取了一个数据类型,它就会一直是这个类型,变量名代表的是用来存放数据的内存位置。而Python中使用的变量名只是各种数据及对象的引用,用id()获取的才是存放数据的内存位置,我们输入的1、1000000000、1.1三个数据均会保存在id()所指示的这些内存位置中,直到垃圾回收把它们拉走,这是动态语言的典型特征,它确定一个变量的类型是在给它赋值的时候。
另一方面,Python又是强类型的,试着运行下边的例子:
#-*-coding:utf-8-*-
"""
我的第一个应用程序
"""
import sys
def Main():
sys.stdout.write("开始程序\n")
i=10
j='虎虎'
print i+j
#下面的语句看起来比较奇怪,一会儿我们会解析它
if __name__=="__main__":
Main()
这个程序会出错,产生一个异常”TypeError:unsupported operand type(s) for +:’int’ and ‘str’”。一个正确的写法是:
#-*-coding:utf-8-*-
"""
我的第一个应用程序
"""
import sys
def Main():
sys.stdout.write("开始程序\n")
i=10
j='虎虎'
print str(i)+j
#下面的语句看起来比较奇怪,一会儿我们会解析它
if __name__=="__main__":
Main()
所以,我们说Python即是一种动态类型语言,同时也是一种强类型的语言,这点是和java不同的地方,对于Python的这种变量的声明、定义、使用方式。Java程序员可能要花一段时间去适应,不过相信你会很快喜欢上它,因为它让事情变的更加简单(而且不会不安全)。
我们再小试牛刀一下,比如我们想看看c盘下面有什么数据与目录的话:
#-*-coding:utf-8-*-
import sys
import os
def main():
sys.stdout.write("Hello World我的第一个程序\n")
print os.listdir("c:/")
if __name__=="__main__":
main()
2) 变量的命名规范
Python与java的变量(函数、类等其他标识符)的命名规范基本一样,同样对大小这与敏感。不一样的地方是Python中以下划线开始或者结束的标识符通常有特殊的意义。例如以一个下划线开始的标识符如_foo不能用from module import *语句导入。前名均有两个下划线的标识符,如__init__被特殊方法保留。前边有两个下划线的标识符,如__bar,被用来实现类私有属性,这个将在“类和面对对象编程”中再说。
最后,Python的关键字不能作为标识符,不过Python的关键字比java要少得多,可以google一下,这里就列出了。
Python没有常量,如果你非要定义常量,可以引用const模块
Python程序中一切数据都是对象,包括自定义对象及基本数据类型,这一点和C#一样,它们都是完全面向对象的语言,所以我想C#程序员很容易理解Python的一切数据都是对象这个口号。
Python不区分值类型和引用类型,你可以把所有的类型都理解为引用类型(当然,它们的实现方式不是一样的,这里只是一个类比)。
Python内建的数据类型有20多种,其中有些不常用到的,有些即将合并。本文将主要介绍空类型、布尔类型、整型、浮点型和字符串、元组、列表、集合、字典等9种Python内置的数据类型。
在这里,我们将前4种称为“简单数据类型”,将后5种称为“高级数据类型”,实际上Python语言本身没有这种叫法,这样分类是我自已设定的,主要是为了和java的相关知识对照方便,希望不要误导大家。
3) 空类型
空类型(None)表示该值是一个空对象,比如没有明确定义返回值的函数就是返回None。空类型没有任何属性,经常被用做函数中可选参数的默认值。None的布尔值为假。
Python的None和java中的可空类型Nullable<T>类似,比如java可以定义Nullable<double> i=null,与Python的空类型类似,但实现原理和用途都不一样。
4) 布尔类型
Python中用True和False来定义真假,你可以直接用a=True或a=False来定义一个布尔型变量,但在Python2.6里,True/False以及None却都不是关键字,在Python3.0里它们已经是关键字了,这个有点乱, 我们可以不用管它,直接使用就OK了。
注意和java不同的是,Python中True和False的首字母要大写。
最后一点,在java中布尔类型和其他类型之间不存在标准的转换。但是在Python中,None、任何数值类型中的0、空字符串’’,空元组(),空列表[],空字典{}都被当作False,其他对象均为True,这点和C++差不多,要提起注意,请思考一下,下面的Python代码会输出什么?
#-*-coding:utf-8-*-
"""
我的第一个应用程序
"""
import sys
def Main():
sys.stdout.write("开始程序\n")
if 0:
print 'True'
else:
print 'False'
#下面的语句看起来比较奇怪,一会儿我们会解析它
if __name__=="__main__":
Main()
5) 数值类型
Python拥有四种数值类型:整型、长整型、浮点类型以及复数类型。
整数类型(int)用来表示从-2147483648到2147483647之间的任意整数(在某些电脑系统上这个范围可能会更大,但绝不会比这个更小);长整型(long)可以表示任意范围的整数,实际上我们把Python的long和int理解为同一种类型就可以了,因为当一个整数超过int的范围后,Python会自动将其升级为长整型。
Python中只有64位双精度浮点数float,与java中的double类型相同(注意在Python中浮点数类型名字是float而不是double),Python不支持32位单精度的浮点数。
除了整数和实数,Python还提供了一种特殊类型复数(complex)。复数使用一对浮点数表示,复数z的实部和虚部分分别用z.real和z.imag访问。
在数值运算中,整数与浮点数运算的结果是浮点数,这就是所谓的“提升规则”,也就是“小”类型会被提升为“大”类型参与计算。这一点和java是一样的,提升的顺序依次为:int long float complex
作为数值类型的最后一个问题,java程序员需要注意的是,Python没有内建的decimal类型,但可以导入decimal模块用来完成与货币相关的计算。
Python中序列是由非负整数索引的对象的有序集合,它包括字符串、Unicode字符串,列表、元组、xrange对象以及缓冲区对象。
6) 字符串类型
Python拥有两种字符串类型:标准字符串(str)是单字节字符序列,Unicode字符串(unicode)是双字节字符序列。
在Python中定义一个标准字符串(str)可以使用单引号、双引号、三引号,这使得Python输入文本比java更方便。比如当Str的内容中包含双引号时,就可以用单引号定义,反之亦然。当字符中有换行符等特殊字符时,可以直接使用三引号定义。这样就方便了很多不用去记那些乱七八糟的转义字符。当然Python也支持转义字符,且含义与java基本一样。
下面是一个例子来说明这一点
#-*-coding:utf-8-*-
"""
我的第一个应用程序
"""
import sys
def Main():
sys.stdout.write("开始程序\n")
str1='i am "python"\n'
str2="i am 'Python' \r"
str3="""
i'm "Python",
<a href="http://www.sina.com.cn"></a>
"""
#你可以把html之类的东西都直接弄进来而不需要处理
print str1,str2,str3
if __name__=="__main__":
Main()
在Python中定义一个Unicode字符串,需要在引号前面加上一个字符u,例如
#-*-coding:utf-8-*-
import sys
def Main():
print u"我是派森"
if __name__=="__main__":
Main()
同时注意,当使用UTF-8编码时,非unicode字符中一个汉字的长度是3,而使用gb2312时是2,见下边代码:
#-*-coding:utf-8-*-
'''
test
'''
import sys
def Main():
print u"我是派森"
unicode =u'我'
str='我'
print len(unicode),len(str)
#输出的 1 3
if __name__=="__main__":
Main()
7) 全局变量
不加入global关键字的话,如果你是在函数内部定义的变量的话,在外部是无法获取的。
#coding:utf-8
def testList():
global list
list=[]
list.append("test1")
list.append("test2")
print list
testList()
print list
三、 基本数据类型-列表(list【】)
Python中列表(list)类似于java中的ArrayList,用于顺序存储结构。列表用符号[]表示,中间的元素可以是任何类型(包括列表本身,以实现多维数组),元素之间用逗号分隔。取值或赋值的时候可以像C数组一样,按位置索引:
#-*-coding:utf-8-*-
import sys
def Main():
array=[1,2,3]
print array[0]
#输出1
array[0]='a'
print array
#输出['a',2,3]
L=[123,'spam',1.23]
#输出大小
print len(L)
print L[0]
print L[:-1]#不包含最后一个
print L+[4,5,6]#重新拼接一个新的列表
if __name__=="__main__":
Main()
从上边的代码中你可能发现一个有趣的事情:在Python的列表中可以混合使用不同类型的数据,像[‘a’,2,3]这样,不过我不建议你这样做,我觉着没有什么好处。
另外还可以看到,列表是可变的序列,也就是说我们可以在“原地”改变列表上某个位置所存储的对象的值。
Python中的list支持多数的操作,同时list也支持“切片”这样的操作。切片指的是抽取序列的一部分,其形式为:list[start:end:step].其抽取规则是:从start开始,每次加上step,直到end为止。默认的step为1;当start没有给出时,默认从list的第一个元素开始;当end=-1时表示list的最后一个元素,依次类推。一些简单的例子见下边代码:
#-*-coding:utf-8-*-
import sys
def Main():
test=['never',1,2,'yes',1,'no','maybe']
print test[0:3]#包括test[0],不包括test[3]
print test[0:6:2]#包括test[0],不包括test[6],而且步长为2
print test[:-1]#包括开始,不包括最后一个
print test[-3:]#抽取最后3个
if __name__=="__main__":
Main()
字符串、列表、元组都支持切片操作,这个很方便,应该学会熟练使用它。
最后,list是Python中最基础的数据结构,你可以把它当作链表、堆栈或队列来使用,效率还不错。Python中没有固定长度数组,如果你确实很在意性能,可以改入array模块来创建一个C风格的数组,它的效率很高,这里就不详细介绍了。
我们还可以对其进行排序与反转
#-*-coding:utf-8-*-
import sys
def Main():
array=[5,2,3,1,8]
array.sort()
for s in array:
print s
array.reverse()
for s in array:
print s
if __name__=="__main__":
Main()
Python核心数据类型的一个优秀的特性就是它们支持任意的嵌套。能够以任意的组合对其进行嵌套。这种特性的一个直接应用就是实现矩阵,或者Python中的多维数组。一个嵌套列表的殂表能够完成这个基本的操作。
#-*-coding:utf-8-*-
import sys
def Main():
M=[[1,2,3],
[4,5,6],
[7,8,9]]
print M[0]
print M[1]
print M[2]
if __name__=="__main__":
Main()
处理序列的操作和列表的方法中,Python还包括了一个更高级的操作,称作列表解析表达式,从而提供了一种处理像矩阵这样结构的强大工具。列如,假设我们需要从列举的矩阵中提取出第二列。因为矩阵是按照行进行存储的,所以可以通过简单的索引即可获得行,使用列表解析可以同样简单地获得列。
#-*-coding:utf-8-*-
import sys
def Main():
M=[[1,2,3],
[4,5,6],
[7,8,9]]
col2=[row[1] for row in M]
print col2
col3=[row[1]+1 for row in M]
print col3
colfilter=[row[1] for row in M if row[1]%2==0]
print colfilter
if __name__=="__main__":
Main()
四、 基本数据类型-字典(dict{})
用过java中的字典的人对Hashtable应该不会陌生,Python里的哈希表就是字典(dict)了。与set类似,字典是一种无序存储结构,它包括关键字(key)和关键字对应的值(value)。
java程序员需要了解的就是,在Python中dict是一种内置的数据类型,定义方式为:
dictionary={key:value}#当有多个键值时,用逗号进行分割。
字典里的关键字为不可变类型,如字符串、整数、只包含不可变对象的元组,列表等不能作为关键字。字典中一个键只能与一个值关联,对于同一个键,后添加的值会覆盖之前的值。
学过数据结构的人对字典的散列查找效率应该都有认识,所以我建议在可能的情况下尽量多用字典,其它的就不多写了。
#-*-coding:utf-8-*-
import sys
if __name__=="__main__":
dict={"a":"apple","b":"banana","g":"grape","o":"orange"}
print dict
print dict["a"]
dict2={1:"apple",2:"banana",3:"grape",4:"orange"}
print dict2
print dict2[1]
#-*-coding:utf-8-*-
import sys
if __name__=="__main__":
#字典的添加、删除、修改操作
dict={"a":"apple","b":"banana","g":"grape","o":"orange"}
dict["w"]="watermelon"
print dict
del(dict["a"])
print dict
print dict.pop("b")
#dict.clear()
#print dict
#字典的遍历
for k in dict:
print "dict[%s]="%k,dict[k]
#-*-coding:utf-8-*-
import sys
if __name__=="__main__":
#字典的keys()与values()方法
dict={"a":"apple","b":"banana","g":"grape","o":"orange"}
#输出key的列表
print dict.keys()
#输出values的列表
print dict.values()
#-*-coding:utf-8-*-
import sys
def Main():
D={'food':'spam','quantity':4,'color':'pink'}
print D['food']
D['quantity']+=1
print D
#另外一种定义字典的方法
D={}
D['name']='Bob'
D['job']='dev'
D['age']=40
print D
#使用键值,进行排序
D={'a':1,'b':2,'c':3}
print D
Ks=D.keys()
print Ks
Ks.sort()
print Ks
for key in Ks:
print key,'=>',D[key]
for key in sorted(D):
print key,'=>',D[key]
#迭代与优化
squares=[x ** 2 for x in [1,2,3,4,5]]
print squares
#与以下代码是等效的
squares=[]
for x in [1,2,3,4,5]:
squares.append(x**2)
if __name__=="__main__":
Main()
在访问的时候,如果这个键值不存在的话,如果我们没有做任何判断的话,会出现错误,这个时候我们可以用以下代码来进行判断。
#-*-coding:utf-8-*-
import sys
def Main():
D={'food':'spam','quantity':4,'color':'pink'}
#测试不存在的键值
if not D.has_key('f'):
print '不存在这个键值'
else:
print D['f']
if __name__=="__main__":
Main()
五、 基本数据类型-元组(tuple())
元组与列表非常相似,它用()而不是[]括起来的序列。元组比列表的速度更快,但元组是一个不可变的序列,也就是与str一样,无法在原位改变它的值。除此之外,其他属性与列表基本一致。
元组是Python中内置的一种数据结构。元组由不同的元素组成,每个元素可以存储不同类型的数据,如字符串、数字甚至元组。元组是写保护的!即元组创建后不能再做任何修改操作,元组通常代表一行数据,而元组中的元素代表不同的数据项。
元组的创建
#-*-coding:utf-8-*-
import sys
if __name__=="__main__":
tuple_name=("apple","banana","grape","orange")
print tuple_name[0]
分片输出
#-*-coding:utf-8-*-
import sys
if __name__=="__main__":
tuple_name=("apple","banana","grape","orange")
print tuple_name[1]
#牛在支持分片输出
print tuple_name[-1]
print tuple_name[-2]
print tuple_name[1:3]
#我还可以在元组中包含自已
print '-----------------'
tuple=(('t1','t2'),('t3','t4'))
print tuple[0][0]
print tuple[1][0]
实现解包的功能
#-*-coding:utf-8-*-
import sys
if __name__=="__main__":
tuple_name=("apple","banana","grape","orange")
a,b,c,d=tuple_name
print a,b,c,d
元组定义的方法与列表类似,不过在定义只包含一个元素的元组时,注意在后边加一个逗号,请体会以下几句的差异:
#-*-coding:utf-8-*-
import sys
def Main():
test=[0] #列表可以这样定义
print type(test) #输出<type 'list'>
test=[0,] #也可以这样定义
print type(test) #输出<type 'list'>
test=(0,) #元组可以这样定义
print type(test) #输出<type 'tuple'>
test=(0) #但不能这样定义,Python会认为它是一个括号表达式
print type(test) #输出<type 'int'>
test=0, #也可以省略括号,但要注意与C的逗号表达式不同
print type(test) #输出<type 'tuple'>
#还可以简单的交换数据
a=1
b=2
a,b=b,a
print a,b
if __name__=="__main__":
Main()
以上这类语句在Python中被广泛应用于变量交换、函数传值等应用,因此Python的解析器在不断对其进行优化,现在已经具备了相当高的效率。所以以上代码在Python2.5以后的版本中,比tmp=a;a=b;b=tmp这种常规语句更快。
l Python是一种动态的强类型语言,在使用变量之前无须定义其类型,但是必须声明和初始化
l “一切命名是引用”,Python中变量名是对象的引用,同一变量名可以在程序运行的不同阶段代表不同类型的数据
l “一切数据都是对象”,Python的所有数据类型都是对象,相较java具有一致的使用方法
l 把问题想得更简单一点,Python的数值类型可以说只有两种:整形和浮点
l 多使用list/tuple/set/dict这几种很pythonic的数据类型,它们分别用[]/()/([])/{}定义
六、 基本数据类型-集合(set)
Python中的set和java中的集合不是一个概念,这是翻译的问题,Python中的集合是指无序的、不重复的元素集,类似数学中的集合概念,可对其进行交、并、差、补等逻辑运算。
常见集合的语法为:s=set([‘a’,’b’,’c’])。不过set在Python3.0中发生了较大的变化,创建一个集合的语法变成了:S={1,2,3},用花括号的方法,与后边要提到的dict类似。
如果在set中传入重复元素,集合会自动将其合并。这个特性非常有用,比如去除列表里大量的重复的元素,用set解决效率很高。示例如下:
#-*-coding:utf-8-*-
import sys
def Main():
a=[133,224,2344,2243,22342,224,133,133,989]
b=set(a)
print b
if __name__=="__main__":
Main()
另一个例子,找出两个list里面相同的元素(集合求交,其它类推),代码如下:
#-*-coding:utf-8-*-
import sys
def Main():
a=[133,224,2344,2243,22342,224,133,133,989]
b=set(a)
print b
a=["11","22","33"]
b=["11","33"]
c=set(a)&set(b)
print c
if __name__=="__main__":
Main()
想想你如果自已实现这个算法会怎么写?然后可以找两个大一点的列表,比比和set实现的效率,你就会有体会了,在以后的程序中多用set吧。
七、 运算符、表达式和流程控制
本章介绍Python的运算符、表达式、程序流程控制语句以及异常处理语句,在这方面,Python和java是非常类似的,我们仅需要注意它们之间的一些细微差异。另外,在本章我还会简要介绍Python语言中的两项有趣功能=列表内涵和动态表达式,虽然它们严格来说属于函数部分的内容,不过我觉得还是放在表达式一章比较合适。
无论使用什么语言,我们编写的大多数代码都包含表达式。一个表达式可以分解为运算符和操作数,运算符的功能是完成某件事,它们由一些数学运算符号或者其他特定的关键字表示,运算符需要数据来进行运算,这样的数据被称为操作数。例如,2+3是一个简单的表达式,其中+是运算符,2和3是操作数。
1) 算术运算符与算术表达式
算术运算符是程序设计语言最基本的运算符。Python提供的算术运算符除了+、-、*、/、%(求余)之外,还提供了两种java中没有提供的运算符:求幂(**)和取整除(//).下面我们就通过一段代码来解析这两个算术运算符的功能。
#-*-coding:utf-8-*-
import sys
def Main():
x=3.3
y=2.2
a=x**y
print a
#输出即3.3的2.2次幂
b=x//y
print b
#输出1.0取整除返回商的整数部分
c=x/y
print c
#输出1.5,注意体会普通除与取整除的区别
if __name__=="__main__":
Main()
2) 赋值运算符与赋值表达式
赋值就是给一个变量赋一个新值,除了简单的=赋值之外,Python和java都支持复合赋值,例如x+=5,等价于x=x+5.
Python不支持java中的自增和自减运算符,例如X++这种语句在Python中会被提示语法有错误。java程序员可能习惯了这种表达式,在Python中,请老老实实的写X+=1就是了。
Python的逻辑运算符与java有较大区别,Python用关键字and or not 代替了java语言中的逻辑运算符 && || !,此外Python中参与逻辑运算符的操作数不限于布尔类型,任何类型的值都可以参与逻辑运算中去。
用逻辑运算符将操作数或表达式连接起来就是逻辑表达式。与java一样,Python中逻辑表达式是短路执行的,也就是说只有需要时才会进行逻辑表达式右边值的计算,例如表达式a and b 只有当a为true时才计算b.思考一下,if(0 and 10/0):这条语句会引发除数为零的异常吗?
此外还要注意:在Python中,and和or所执行的逻辑运算并不返回布尔值,而是返回它们实际进行比较的值之一。下边是一个例子:
#-*-coding:utf-8-*-
import sys
def Main():
print 'a' and 'b'
print '' and 'b'
if __name__=="__main__":
Main()
3) 关系运算符与关系表达式
关系运算符实际上是逻辑运算的一种,关系表达式的返回值总是布尔值。Python中的比较操作符与java完全是一样的,包括== != > < >= <=共6种。
除了基本的变量比较外,Python的关系运算符还包括身份运算符is.在Python中,is用来检验两个对象在内存中是否指向同一个对象(还记得一切数据皆对象吗?一切命名皆引用吗)。
三元运算符
三元运算符是c/c++系语言所特有的一类运算符,例如,对表达式b?x:y,先计算条件b,然后进行判断,如果b的值为true,则计算并返回x的值,否则计算并返回y的值。
在Python中,提供了专门的逻辑分支表达式来模拟java系中的三元运算,我们也可以在一行语句中完成三元运算,例如
print ‘偶数’ if x%2==0 else ‘奇数’
八、 流程控制
1) 条件语句
Python用if,elif,else这三个关键字进行条件判断,与java唯一的区别就是用elif取代else if,少打两个字,其它都一样,此外别忘了在if等语句后加:号
如果一个流程控制分南下不做任何事情,记得写一句pass语句,不然Python会报错。例如:
if 0:
pass #这一句语没有什么意义
在Python中没有switch语句,你可以使用if..elif..else语句来完成同样的工作。如果你觉得繁琐,可以试试dict实现的方式,下边是一个例子,分别对比了两种实现方式。
#-*-coding:utf-8-*-
import sys
def Main():
#使用if替代
x='4'
print "OK"
if x=='1':
print 'one'
elif x=='2':
print 'two'
else:
print 'nothing!'
#使用dict
numtrans={
1:'one',
2:'two',
3:'three'
}
try:
print numtrans[x]
except KeyError:
print 'nothing!'
if __name__=="__main__":
Main()
2) 循环
Python支持两种循环语句while循环和for循环,不支持java中的do-while循环。在Python的while循环和Java基本一致,此处我们着重比较两种语言中的for循环的区别。
说的简单一点,python中的for语句相当于java中的foreach语句,它用于从集合对象(list/str/tuple等)中遍历数据。例如:
for I in [1,2,3,4,5]:
print i
for I in range(10):
print i
#-*-coding:utf-8-*-
import sys
if __name__=="__main__":
tuple=(("apple","banana"),("grape","orange"))
for i in range(50,100+1):
print i
#-*-coding:utf-8-*-
import sys
if __name__=="__main__":
for i in range(50,100+1):
print i
range(1,5) #代表从1到5(不包含5)
range(1,5,2) #代表从1到5,间隔2(不包含5)
range(5) #代表从0到5(不包含5)
__author__ = 'TenYear'
#-*-coding:utf-8-*-
"""
my fist App
"""
import sys
import urllib
def Main():
itemlist=[1,2,3,4,5,4]
for m in itemlist:
print m
#this is test
if __name__=="__main__":
Main()
九、 异常
Python和java一样支持异常处理,利用try/except/finally结构,可以很方便的捕获异常,同时可以用raise语句手动抛出异常(上述四个异常处理的关键字分别对就应Java中的try/catch/finally/throw).通过except,您可以将try标示的语句中出现的错误和异常捕获。
#-*-coding:utf-8-*-
import sys
def Main():
try:
f=open('firstpython.py')
s=f.readline()
print s
except IOError,(errno,strerror):
print "I/O error(%s):%s" %(errno,strerror)
except ValueError:
print "Could not convert data to an integer"
except:
print "Unexpected error:",sys.exc_info()[0]
raise
finally:
f.close()
if __name__=="__main__":
Main()
最后说明一点,python的try也支持else语句,如果有一些代码要在try没有发生异常的情况下才执行,就可以把它放在else中。
十、 动态表达式
在C#语言中,如果需要在文本框中输入1+2(或更加复杂的数学表达式)后计算它的值,可能会用到表达式解析等。现在我们有了Python,要完成这种任务可以说是非常简单:只要用内置的eval()函数,就可以计算并返回任意有效表达式的值。例如:
str=’1+2’
print eval(str)
除了eval函数之外,Python还提供了exec语句将字符串str当成有效Python代码来执行,看下面的例子:
exec ‘a=100’
print a
另外还有execfile函数,它用来执行一个外部的py文件,上一个例子存为exec.py后,运行下边的代码就知道是怎么回事了:
execfile(r’c:\exec.py’)
最后提醒,默认的eval(),exec,execfile()所运行的代码都位于当前的名字空间中,eval(),exec,和execfile()函数也可以接受一个或两个可选字典参数作为代码执行的全局名字空间和局部名字空间,具体可以参考Python手册。
列表内涵是Python最强有力的语法之一,常用于从集合对象中有选择地获取并计算元素,虽然多数情况下可以使用for/if等语句组合完成同样的任务,但列表内涵书写的代码更加简洁。
#-*-coding:utf-8-*-
import sys
def func():
x=1
y=2
m=3
n=4
sum=lambda x,y:x+y
print sum
sub=lambda m,n:m-n
print sub
return sum(x,y)*sub(m,n)
if __name__=="__main__":
print func()
列表内涵的一般形式如下,我们可以把[]内的列表内涵写为一行,也可以写为多行。
[表达式 for item1 in 序列1 … for itemN in 序列N if 条件表达式]
上面的表达式分为三部分,最左边是生成每个元素的表达式,然后是for迭代过程,最右边可以设定一个if判断作为过滤条件。
列表内涵的一个著名例子是生成九九乘法表:
s=[(x,y,x*y) for x in range(1,10) for y in range(1,10) if x>=y]
十一、 函数及函数编程
在java中没有独立的函数存在,只有类的(动态或静态)方法这一概念,它指的是类中用于执行计算或其它行为的成员。在Python中,你可以使用类似C#的方式定义类的动态或静态成员方法,因为它与java一样支持完全的面向对象编程。你也可以用过程式编程的方式来编写Python程序,这时Python中的函数与类可以没有任何关系,类似C语言定义和使用函数的方式。此外,Python还支持函数式编程,虽然它对函数编程的支持不如LISP等语言那样完备,但适合使用还是可以提高我们工作的效率的。
1) 函数的定义
函数定义是最基本的行为抽象代码,也是软件复用最初级的方式。Python中函数的定义语句由def关键字、函数名、括号、参数及冒号组成。下面是几个简单的函数定义语句:
#-*-coding:utf-8-*-
import sys
def Main():
def F1():
print "我是F1"
def F2(x,y):
a=x+y
return a
#定义有多个返回值的函数,用逗号分割不同的返回值,
#返回结果是一个元组
def F3(x,y):
a=x/y
b=x%y
return a,b
if __name__=="__main__":
Main()
可能你已经注意到了,Python定义函数的时候并没有约束参数的类型,它以最简单的形式支持了泛型编程。你可以输入任意类型的数据作为参数,只要这些类型支持函数内部的操作
2) 定义一个交换函数
#-*-coding:utf-8-*-
import sys
import random
def compareNum(num1,num2):
if(num1>num2):
return 1
elif(num1==num2):
return 0
else:
return -1
if __name__=="__main__":
num1=random.randrange(1,9)
num2=random.randrange(1,9)
print "num1=",num1
print "num2=",num2
print compareNum(num1,num2)
3) 函数的默认参数与返回值
#-*-coding:utf-8-*-
import sys
def arithmetic(x=1,y=1,operator="+"):
result={
"+":x+y,
"-":x-y,
"*":x*y,
"/":x/y
}
return result.get(operator)
if __name__=="__main__":
print arithmetic(1,2)
print arithmetic(1,2,"-")
4) 返回多个值
Python支持多个返回值
#coding:utf-8
def testList():
return "aaa","bbb"
a,b=testList()
print a
print b
5) locals函数和globals函数介绍
Python有两个内置的函数,locals() 和globals(),它们提供了基于字典的访问局部和全局变量的方式。首先,是关于名字空间的一个名词解释。是枯燥,但是很重要,所以要耐心些。Python使用叫做名字空间的东西来记录变量的轨迹。名字空间只是一个字典,它的键字就是变量名,字典的值就是那些变量的值。实际上,名字空间可以象Python的字典一样进行访问,一会我们就会看到。
在一个Python程序中的任何一个地方,都存在几个可用的名字空间。每个函数都有着自已的名字空间,叫做局部名字空间,它记录了函数的变量,包括 函数的参数和局部定义的变量。每个模块拥有它自已的名字空间,叫做全局名字空间,它记录了模块的变量,包括函数、类、其它导入的模块、模块级的变量和常量。还有就是内置名字空间,任何模块均可访问它,它存放着内置的函数和异常。
当一行代码要使用变量 x 的值时,Python会到所有可用的名字空间去查找变量,按照如下顺序:
1.局部名字空间 - 特指当前函数或类的方法。如果函数定义了一个局部变量 x,Python将使用这个变量,然后停止搜索。
2.全局名字空间 - 特指当前的模块。如果模块定义了一个名为 x 的变量,函数或类,Python将使用这个变量然后停止搜索。
3.内置名字空间 - 对每个模块都是全局的。作为最后的尝试,Python将假设 x 是内置函数或变量。
如果Python在这些名字空间找不到 x,它将放弃查找并引发一个 NameError 的异常,同时传递 There is no variable named 'x' 这样一条信息,象Python中的许多事情一样,名字空间在运行时直接可以访问。特别地,局部名字空间可以通过内置的 locals 函数来访问。全局(模块级别)名字空间可以通过 globals 函数来访问
#coding:utf-8
from __future__ import unicode_literals
from sys import *
def test(arg):
#函数test在它的局部名字空间中有两个变量:arg(它的值被传入函数)
# 和z(它在函数内部)
z=1
print locals()
#locals返回一个名字与值的字典,这个字典的键字是字符串形式的变量名
#字典的值是变量的实际值
test(5)
test('楚广明')
print globals()#返回一个全局的字典,包括所有导入的变量