初学python:《简明python教程》的学习笔记

学习python的缘由

决心在一个这个寒假更加深入学习推荐系统之后,本来打算看数据挖掘导论或者是数据挖掘:概念与技术。不过在询问过一位学长之后,他推荐我看一看更加基础的书:集体智慧编程。该书所有的代码都是由python完成,在阅读了前4章之后,深刻觉得需要系统学习一下python。而且当时学长也说了,要学机器学习,python是必学的,而且python也不难。所以更加坚定了学习python的决心。故搜索到这本python最基础的书:简明python教程,作者:Swaroop C. H。译者:沈洁元。说完缘由之后让我正式进入简明python教程的学习吧。


网友建议学习python的书

网友给出了学习python一系列的书,如下所示。

  1. 学习《A Byte of Python》,中文译名为《Python简明教程》,全书下来只有100多页,简单干练,通俗易懂,是公认的Python入门教程。我虽然下到了《Python简明教程》pdf版,但是觉得其中的代码可能是因为译者转换文档类型的原因,格式变得很乱,所以准备尽量阅读英文原版。网络上也有《Python简明教程》的word版,不想看英文的朋友可以找一下。 
  2. 我买了一本影印版的《Learning Python》第三版,用于精读。现在能买到的版本比较新的Python经典书籍一共有两本,一本是《Learning Python》第三版,一本是《Python核心编程》第二版。本来是想买后者的,因为看中文毕竟要比看英文来的快一些,不过看了下书评,《Python核心编程》第二版居然是一个叫宋X广的IT败类把CPUG论坛上大家共同翻译的成果占为己有,属上了自己的名字!(详细事件经过可以看china-pub或者dangdang对这本书的点评,也可以看这里http://groups.google.com/group/python-cn/browse_thread/thread/e5e465336fdeb03c?hl=zh-CN)我觉得如果是买这本书,让这样的人赚取稿费,太不值得了,所以退而求其次,买了本影印版的《Learning Python》第三版。而且我还下到了《Python核心编程》第二版的pdf版本,非常清晰,如果大家想要,可以到http://onlypython.group.javaeye.com/去下载。 
  3. 准备把《Dive into Python》(中文译名为《深入Python》),《Core Python Programming》第二版(中文译名为《Python核心编程》)作为《Learning Python》的补充材料来阅读。 
  4. 准备深入学习《Python for Unix and.Linux System Administration》,《foundations of python network programming》,《wxPython in action》等高级编程。

书中开篇感悟

还没开始学具体的知识就先学点人生感悟两句:
  • 有两种方式构建软件设计:一种是把软件做得很简单以至于明显找不到缺陷;另一种是把它做得很复杂以至于找不到明显的缺陷。——C.A.R. Hoare
  • 获得人生中的成功需要的专注与坚持不懈多过天才与机会。——C.W. Wendte

第1章介绍

简介中,说python是一个脚本语言。
我认为最关键的有两点可以帮助我们理解什么是脚本语言。

  • 脚本语言一般都是以文本形式存在,类似于一种命令。
    举个例子说:如果建立了一个程序,叫aaa.exe,可以打开.aa为扩展名的文件,为.aa文件的编写指定了一套规则(语法),当别人编写了.aa文件后,自己的程序用这种规则来理解编写人的意图,并作出回应,那么,这一套规则就是脚本语言。
  • 脚本语言一般都有相应的脚本引擎来解释执行。 他们一般需要解释器才能运行。Python、JAVASCRIPT,ASP,PHP,PERL,Nuva都是脚本语言。C/C++编译、链接后,可形成独立执行的exe文件。

python的特色有点多,但是我认为其中重要的有:


解释性 
这一点需要一些解释。
一个用编译性语言比如C或C++写的程序可以从源文件(即C或C++语言)转换到一个你的计算机使用的语言(二进制代码,即0和1)。这个过程通过编译器和不同的标记、选项完成。当你运行你的程序的时候,连接/转载器软件把你的程序从硬盘复制到内存中并且运行。

而Python语言写的程序不需要编译成二进制代码。你可以直接从源代码 运行 程序。在计算机内部,Python解释器把源代码转换成称为字节码的中间形式,然后再把它翻译成计算机使用的机器语言并运行。事实上,由于你不再需要担心如何编译程序,如何确保连接转载正确的库等等,所有这一切使得使用Python更加简单。由于你只需要把你的Python程序拷贝到另外一台计算机上,它就可以工作了,这也使得你的Python程序更加易于移植。

上文拷贝自原书,显然C/C++的
运作模式我们还是知道的,但是python的的方式我还是第一次接触,简单说了,python的脚本语言被解释器处理成了字节码,字节码被处理成了机器语言,并运行。


可扩展性 
如果你需要你的一段关键代码运行得更快或者希望某些算法不公开,你可以把你的部分程序用C或C++编写,然后在你的Python程序中使用它们。
很显然这表明python可以调用C/C++的代码。


 

第2章 安装python

 

作者表明linux下都默认装了python
而windows下,只需要下载 一个软件,然后安装,然后在设置一下环境变量即可。
摘自原文:
在Windows命令行中使用Python
如果你想要从Windows命令行调用Python,那么你需要先正确的设置PATH变量。
对于Windows 2000、XP、2003,点击控制面板->系统->高级->环境变量。在“系统变量”表单中点击叫做PATH的变量,然后编辑这个变量,把;C:\Python23加到它的结尾。当然,是Python所在的正确目录名。


第3章 最初的步骤

 

首先进入python模式,可以再命令行或者shell打印python,也可以直接使用idle。


>>> print 'hello world'
hello world
>>> 

第二句是打印出来的,然而我试了一下“”,发现也是可以得。


关于选择一个编辑器,这是因为python对文本缩进,有非常严格的要求,所以书中不建议你用notepad,建议我们寻找一个有语法加亮的工具,我相信在linux我肯定使用vim,然后在windows下,我打算使用python程序里面自带的一个编辑器,我只需要右键一个.py的文件,然后点击edit with idle即可,在里面输入好代码之后,使用菜单Edit->Run Script或者使用键盘快捷方式Ctrl-F5都行。
注意python对大小写很进行了区分。
注释是用#,相当于C里面的//
第3章 最初的步骤 可执行的Python程序 部分主要讲了一下在linux下的环境变量问题。


获取帮助 

 

非常重要了
对某一个python里感兴趣,在试着用help命令,比如help(str),help('print')。第二个必须要用引号的原因是,如果不使用引号,将会让人解释器认为你是想要打印任何东西,而现在你只是想要print的字符串。
另外直接键入help()可以进入到帮助页面。

第4章 基本概念

 

数 

 

在Python中有4种类型的数——整数、长整数、浮点数和复数。

  1. 2是一个整数的例子。 
  2. 长整数不过是大一些的整数。 
  3. 3.23和52.3E-4是浮点数的例子。E标记表示10的幂。在这里,52.3E-4表示52.3 * 10-4。 
  4. (-5+4j)和(2.3-4.6j)是复数的例子。 


字符串 

使用单引号(') 
你可以用单引号指示字符串,就如同'Quote me on this'这样。所有的空白,即空格和制表符都照原样保留。

使用双引号(") 
在双引号中的字符串与单引号中的字符串的使用完全相同,例如"What's your name?"。

使用三引号('''或""") 
利用三引号,你可以指示一个多行的字符串。你可以在三引号中自由的使用单引号和双引号。例如:

'''This is a multi-line string. This is the first line.
This is the second line.
"What's your name?," I asked.
He said "Bond, James Bond."
'''

转义符 
这个和平常的使用差不多
要表示:What's your name?。
可以使用:'What\'s your name?'

你可以用转义符\\来指示反斜杠本身
最大的不同在于:
在一个字符串中,行末的单独一个反斜杠表示字符串在下一行继续,而不是开始一个新的行。例如:

"This is the first sentence.\
This is the second sentence." 

等价于"This is the first sentence. This is the second sentence."

自然字符串 
如果你想要指示某些不需要如转义符那样的特别处理的字符串,那么你需要指定一个自然字符串。自然字符串通过给字符串加上前缀r或R来指定。例如r"Newlines are indicated by \n"。
加r和不加r的区别在于,加了r之后,就\n被认为是一个字符,而不是换行符

Unicode字符串 
Unicode是书写国际文本的标准方法。如果你想要用你的母语如北印度语或阿拉伯语写文本,那么你需要有一个支持Unicode的编辑器。类似地,Python允许你处理Unicode文本——你只需要在字符串前加上前缀u或U。例如,u"This is a Unicode string."。
记住,在你处理文本文件的时候使用Unicode字符串,特别是当你知道这个文件含有用非英语的语言写的文本。

最后一句再读一遍哈

 

常量

 

字符串是不可变的
这意味着一旦你创造了一个字符串,你就不能再改变它了。虽然这看起来像是一件坏事,但实际上它不是。我们将会在后面的程序中看到为什么我们说它不是一个缺点。

按字面意义级连字符串 
如果你把两个字符串按字面意义相邻放着,他们会被Python自动级连。例如,'What\'s' 'your name?'会被自动转为"What's your name?"。

记住,单引号和双引号字符串是完全相同的——它们没有在任何方面有不同。 

标识符的命名

 

  • 标识符 是用来标识 某样东西 的名字。在命名标识符的时候,你要遵循这些规则:
  • 标识符的第一个字符必须是字母表中的字母(大写或小写)或者一个下划线(‘ _ ’)。
  • 标识符名称的其他部分可以由字母(大写或小写)、下划线(‘ _ ’)或数字(0-9)组成。
  • 标识符名称是对大小写敏感的。例如,myname和myName不是一个标识符。注意前者中的小写n和后者中的大写N。
  • 有效 标识符名称的例子有i、__my_name、name_23和a1b2_c3。
  • 无效 标识符名称的例子有2things、this is spaced out和my-name。

 

对象 

 

给C/C++程序员的注释
使用变量时只需要给它们赋一个值。不需要声明或定义数据类型。 

比如:
i = 5
print i
i = i + 1
print i

你没使用int指明数据类型吧

 

逻辑行与物理行

 

虽然python里面有分号,但是一般不用。因为不用的时候看起来更方便。
>>> i = 5 print i
SyntaxError: invalid syntax
>>> i = 5 ; print i
5
>>> 
分号可以用来表示逻辑行的结束,当时当我们使用
i=5
print 5

这样的形式的时候将不需要考虑这个问题。
 

缩进

 

事实上行首的空白是重要的。它称为缩进。
同一层次的语句必须有相同的缩进。每一组这样的语句称为一个块。
不要混合使用制表符和空格来缩进,因为这在跨越不同的平台的时候,无法正常工作。我 强烈建议 你在每个缩进层次使用 单个制表符 或 两个或四个空格 。

我觉得使用一个制表符更方便吧 


第5章 运算符与表达式  

 

简介 

 

居然在这个地方把操作数看懂了
一个简单的表达式例子如2 + 3。一个表达式可以分解为运算符和操作数。
运算符 的功能是完成某件事,它们由如+这样的符号或者其他特定的关键字表示。运算符需要数据来进行运算,这样的数据被称为 操作数 。在这个例子中,2和3是操作数。


运算符 

 

表5.1 运算符与它们的用法
很重要,但是也没必要全部记,我打算贴在这里,遇见不懂的时候查一下就好了。
运算符 名称 说明 例子
+ 两个对象相加 3 + 5得到8。'a' + 'b'得到'ab'。
- 得到负数或是一个数减去另一个数 -5.2得到一个负数。50 - 24得到26。
* 两个数相乘或是返回一个被重复若干次的字符串 2 * 3得到6。'la' * 3得到'lalala'。
**

返回x的y次幂

3 ** 4得到81(即3 * 3 * 3 * 3)
/ x除以y 4/3得到1(整数的除法得到整数结果)。4.0/3或4/3.0得到1.3333333333333333
// 取整除 返回商的整数部分 4 // 3.0得到1.0
% 取模 返回除法的余数 8%3得到2。-25.5%2.25得到1.5
<< 左移 把一个数的比特向左移一定数目(每个数在内存中都表示为比特或二进制数字,即0和1) 2 << 2得到8。——2按比特表示为10
>> 右移 把一个数的比特向右移一定数目 11 >> 1得到5。——11按比特表示为1011,向右移动1比特后得到101,即十进制的5。
& 按位与 数的按位与 5 & 3得到1。
| 按位或 数的按位或 5 | 3得到7。
^ 按位异或 数的按位异或 5 ^ 3得到6
~ 按位翻转 x的按位翻转是-(x+1) ~5得到6。
< 小于 返回x是否小于y。所有比较运算符返回1表示真,返回0表示假。这分别与特殊的变量True和False等价。注意,这些变量名的大写。 5 < 3返回0(即False)而3 < 5返回1(即True)。比较可以被任意连接:3 < 5 < 7返回True。
> 大于 返回x是否大于y 5 > 3返回True。如果两个操作数都是数字,它们首先被转换为一个共同的类型。否则,它总是返回False。
<= 小于等于 返回x是否小于等于y x = 3; y = 6; x <= y返回True。
>= 大于等于 返回x是否大于等于y x = 4; y = 3; x >= y返回True。
== 等于 比较对象是否相等 x = 2; y = 2; x == y返回True。x = 'str'; y = 'stR'; x == y返回False。x = 'str'; y = 'str'; x == y返回True。
!= 不等于 比较两个对象是否不相等 x = 2; y = 3; x != y返回True。
not 布尔“非” 如果x为True,返回False。如果x为False,它返回True。 x = True; not y返回False。
and 布尔“与” 如果x为False,x and y返回False,否则它返回y的计算值。 x = False; y = True; x and y,由于x是False,返回False。在这里,Python不会计算y,因为它知道这个表达式的值肯定是False(因为x是False)。这个现象称为短路计算。
or 布尔“或” 如果x是True,它返回True,否则它返回y的计算值。 x = True; y = False; x or y返回True。短路计算在这里也适用。

 

运算符优先级 

 

老生常谈的问题,直接看表吧,由上到下,由低到高。
表5.2 运算符优先级
运算符 描述
lambda Lambda表达式
or 布尔“或”
and 布尔“与”
not x 布尔“非”
in,not in 成员测试
is,is not 同一性测试
<,<=,>,>=,!=,== 比较
| 按位或
^ 按位异或
& 按位与
<<,>> 移位
+,- 加法与减法
*,/,% 乘法、除法与取余
+x,-x 正负号
~x 按位翻转
** 指数
x.attribute 属性参考
x[index] 下标
x[index:index] 寻址段
f(arguments...) 函数调用
(experession,...) 绑定或元组显示
[expression,...] 列表显示
{key:datum,...} 字典显示
'expression,...' 字符串转换

 

结合规律
运算符通常由左向右结合,即具有相同优先级的运算符按照从左向右的顺序计算。例如,2 + 3 + 4被计算成(2 + 3) + 4。

一些如赋值运算符那样的运算符是由右向左结合的,即a = b = c被处理为a = (b = c)。

 


第6章 控制流 

 

if语句 

 

在我来看,唯一新鲜的就是有一个elif的关键字,它是if和else的结合。
给C/C++程序员的注释
在Python中没有switch语句。你可以使用if..elif..else语句来完成同样的工作(在某些场合,使用字典会更加快捷。) 

 

while语句 

 

重点是多了一个else句:
给C/C++程序员的注释
记住,你可以在while循环中使用一个else从句。 

类似于下面所示的,
while flag:
    
else:
    print 'The while loop is over.'  


当while循环条件变为False的时候,else块才被执行——这甚至也可能是在条件第一次被检验的时候。如果while循环有一个else从句,它将始终被执行,除非你的while循环将永远循环下去不会结束!



 

for循环 

 

这个不同之处多一些,请看例子:
for i in range(1, 5):
    print i
else:
    print 'The for loop is over' 
输出:
>>> 
1
2
3
4
over!
>>> 
其中:for..in是另外一个循环语句,它在一序列的对象上 递归 即逐一使用队列中的每个项目
而对于range也必须有很好的理解:
range返回一个序列的数。这个序列从第一个数开始到第二个数为止。 例如,range(1,5)给出序列[1, 2, 3, 4]。注意不包括5。
默认地,range的步长为1。如果我们为range提供第三个数,那么它将成为步长。例如,range(1,5,2)给出[1,3]。记住,range 向上 延伸到第二个数,即它不包含第二个数。
所以,for i in range(1,5)等价于for i in [1, 2, 3, 4]
同样,else部分是可选的。如果包含else,它总是在for循环结束后执行一次,除非遇到break语句。
给C/C++程序员的注释

在C/C++中,如果你想要写for (int i = 0; i < 5; i++),那么用Python,你写成for i in range(0,5)。

 


break语句 

 

break语句是用来 终止 循环语句的,即哪怕循环条件没有称为False或序列还没有被完全递归,也停止执行循环语句。
一个重要的注释是,如果你从for或while循环中 终止 ,任何对应的循环else块将不执行。

最后一句重点哈。回答:执行是不执行?

 


第7章 函数 

 

局部变量 

 

重点是如何将局部变量改为全局变量。
代码:
def func(x):
    print 'x is', x
    x = 2
    print 'Changed local x to', x


x = 50
func(x)
print 'x is still', x
输出:
x is 50
Changed local x to 2
x is still 50 

但是如果我们想在函数中改变主块中的x呢?使用global关键字
代码:

def func(): global x print 'x is', x x = 2 print 'Changed local x to', xx = 50func()print 'Value of x is', x

输出:
x is 50
Changed global x to 2
Value of x is 2  

 

默认参数值 

 

代码:
def say(message, times = 1):
    print message * times


say('Hello')
say('World', 5) 

输出:
Hello
WorldWorldWorldWorldWorld 

很有趣的是,这里学习到了print的一个用法,原来还可以这么玩。
注意:只有在形参表末尾的那些参数可以有默认参数值。例如,def func(a, b=5)是有效的,但是def func(a=5, b)是 无效 的。

 

关键参数 

 

对函数参数的赋值,不一定依据位置,还可以依据其形参的变量名。
代码:
def func(a, b=5, c=10):
    print 'a is', a, 'and b is', b, 'and c is', c


func(3, 7)
func(25, c=24)
func(c=50, a=100) 
输出:
a is 3 and b is 7 and c is 10
a is 25 and b is 5 and c is 24
a is 100 and b is 5 and c is 50 

在第三次使用func(c=50, a=100)的时候,我们使用关键参数来完全指定参数值。注意,尽管函数定义中,a在c之前定义,我们仍然可以在a之前指定参数c的值。 


 

return语句 

 

注意,没有返回值的return语句等价于return None。None是Python中表示没有任何东西的特殊类型。例如,如果一个变量的值为None,可以表示它没有值。
除非你提供你自己的return语句,每个函数都在结尾暗含有return None语句。通过运行print someFunction(),你可以明白这一点,函数someFunction没有使用return语句,如同:
代码:
def somefuntion():
    pass
print somefuntion()
输出:
>>> 
None
>>> 

 

DocStrings 

 

这其实是告诉我们一种方式:给函数写说明的方式。
代码:
def printMax(x, y):
    '''Prints the maximum of two numbers.


    The two values must be integers.'''
    x = int(x) # convert to integers, if possible
    y = int(y)


    if x > y:
        print x, 'is maximum'
    else:
        print y, 'is maximum'


printMax(3, 5)
print printMax.__doc__ 
其中__是双下划线。两下哈
输出:
5 is maximum
Prints the maximum of two numbers.


        The two values must be integers. 
你也可以调用help(printMax)来查看这个函数的说明,如下所示:
>>> help(printMax)
Help on function printMax in module __main__:


printMax(x, y)
    Prints the maximum of two numbers.
    
    The two values must be integers.

需要注意要写这个东西的话:
在函数的第一个逻辑行写这个说明,文档字符串的惯例是一个多行字符串,它的首行以大写字母开始,句号结尾。第二行是空行,从第三行开始是详细的描述。 强烈建议 你在你的函数中使用文档字符串时遵循这个惯例。


 

第8章 模块 

 

简介 

 

模块基本上就是一个包含了所有你定义的函数和变量的文件。为了在其他程序中重用模块,模块的文件名必须以.py为扩展名。
首先,我们将学习如何使用标准库模块。
例8.1 使用sys模块
代码:
import sys


print 'The command line arguments are:'
for i in sys.argv:
    print i


print '\n\nThe PYTHONPATH is', sys.path, '\n' 


输出:

$ python using_sys.py we are arguments
The command line arguments are:
using_sys.py
we
are
arguments



The PYTHONPATH is ['/home/swaroop/byte/code', '/usr/lib/python23.zip',
'/usr/lib/python2.3', '/usr/lib/python2.3/plat-linux2',
'/usr/lib/python2.3/lib-tk', '/usr/lib/python2.3/lib-dynload',
'/usr/lib/python2.3/site-packages', '/usr/lib/python2.3/site-packages/gtk-2.0']

 

 
  

我对这段代码唯一觉得奇怪的地方就是为什么sys.argv就是我输入的argv呢?难道就是因为我import了sys,所以把我输入的文件名和参数一起给了sys.argv,只能这样解释了

 

字节编译的.pyc文件 

 

输入一个模块相对来说是一个比较费时的事情,所以Python做了一些技巧,以便使输入模块更加快一些。一种方法是创建 字节编译的文件 ,这些文件以.pyc作为扩展名。字节编译的文件与Python变换程序的中间状态有关。当你在下次从别的程序输入这个模块的时候,.pyc文件是十分有用的——它会快得多,因为一部分输入模块所需的处理已经完成了。另外,这些字节编译的文件也是与平台无关的。所以,现在你知道了那些.pyc文件事实上是什么了。

 

from..import语句 

 

如果你想要直接输入argv变量到你的程序中(避免在每次使用它时打sys.),那么你可以使用from sys import argv语句。如果你想要输入所有sys模块使用的名字,那么你可以使用from sys import *语句。这对于所有模块都适用。一般说来,应该避免使用from..import而使用import语句,因为这样可以使你的程序更加易读,也可以避免名称的冲突。

那这个知识点不讲也罢,注意最后一句话,不建议用from语句。

 

模块的__name__ 

 

关键是import一个模块会导致这个模块的代码被运行,这个模块是自身运行还是被别的模块import后运行的呢?我们可以通过if __name__ == '__main__'这样一个语句来判断,并且做相应的操作。代码:

# Filename: using_name.py


if __name__ == '__main__':
    print 'This program is being run by itself'
else:
    print 'I am being imported from another module' 

输出:

$ python using_name.py
This program is being run by itself


$ python
>>> import using_name
I am being imported from another module
>>> 

制造你自己的模块 

 

这个其实本身没有多大的意义。
因为只是把函数和变量封装的另一个py文件里,如果要用到别的py文件,请使用import关键字,当然你也可以使用from ... import ... 只引进你需要的方法和变量。

经过测试发现只用import关键字的话,那么文件必须放在相同目录下。

 

dir()函数 

 

>>> import testA
>>> dir(testA)
['__builtins__', '__doc__', '__file__', '__name__', '__package__', 'sayhi', 'version']
>>> dir()
['__builtins__', '__doc__', '__name__', '__package__', 'testA']
>>> a = 5
>>> dir()
['__builtins__', '__doc__', '__name__', '__package__', 'a', 'testA']
>>> del a
>>> dir()
['__builtins__', '__doc__', '__name__', '__package__', 'testA']
>>> 


你可以使用内建的dir函数来列出模块定义的标识符。标识符有函数、类和变量。

当你为dir()提供一个模块名的时候它返回模块定义的名称列表。如果不提供参数,它返回当前模块中定义的名称列表。

如上就是做了就些测试,比如我们可以添加了a之后,看看dir(),也可以将del删除掉。
我们还可以观察在那份testA中,sayhi是一个函数,但是version是一个名字,但是我们无法使用dir()函数看出它到底是一个变量还是一个函数。

第9章 数据结构

 

简介 

 

数据结构基本上就是——它们是可以处理一些 数据 的 结构 。或者说,它们是用来存储一组相关数据的。
在Python中有三种内建的数据结构——列表、元组和字典


 

列表

 

那么多废话还不如看了一个例子
注意list是一个[]括号。
代码:

shoplist = ['apple', 'mango', 'carrot', 'banana']


print 'I have', len(shoplist),'items to purchase.'


print 'These items are:', # Notice the comma at end of the line
for item in shoplist:
    print item,


print '\nI also have to buy rice.'
shoplist.append('rice')
print 'My shopping list is now', shoplist


print 'I will sort my list now'
shoplist.sort()
print 'Sorted shopping list is', shoplist


print 'The first item I will buy is', shoplist[0]
olditem = shoplist[0]
del shoplist[0]
print 'I bought the', olditem
print 'My shopping list is now', shoplist 


输出:

I have 4 items to purchase.
These items are: apple mango carrot banana
I also have to buy rice.
My shopping list is now ['apple', 'mango', 'carrot', 'banana', 'rice']
I will sort my list now
Sorted shopping list is ['apple', 'banana', 'carrot', 'mango', 'rice']
The first item I will buy is apple
I bought the apple
My shopping list is now ['banana', 'carrot', 'mango', 'rice'] ‘

其中顺便讲了一下
shoplist 作为一个list的类的对象,那么他才可以调用append、sort、方法。


元组 


这个玩意很有意思,倒不是其含义有意思,倒是其在例子中是一个用法很有意思。就是在元组中再加一个元组就会形成二维数组的感觉。


代码:

zoo = ('wolf', 'elephant', 'penguin')
print 'Number of animals in the zoo is', len(zoo)


new_zoo = ('monkey', 'dolphin', zoo)
print 'Number of animals in the new zoo is', len(new_zoo)
print 'All animals in new zoo are', new_zoo
print 'Animals brought from old zoo are', new_zoo[2]
print 'Last animal brought from old zoo is', new_zoo[2][2] 




输出:

Number of animals in the zoo is 3
Number of animals in the new zoo is 3
All animals in new zoo are ('monkey', 'dolphin', ('wolf', 'elephant', 'penguin'))
Animals brought from old zoo are ('wolf', 'elephant', 'penguin')
Last animal brought from old zoo is penguin 



打印时也使用了元组,不过我对这个并不陌生。
代码:

age = 22
name = 'Swaroop'


print '%s is %d years old' % (name, age)
print 'Why is %s playing with that python?' % name 


输出:

Swaroop is 22 years old
Why is Swaroop playing with that python?


字典

 

看一个例子吧,例子中还有一些常用的函数。
代码:

ab = {       'Swaroop'   : '[email protected]',
             'Larry'     : '[email protected]',
             'Matsumoto' : '[email protected]',
             'Spammer'   : '[email protected]'
     }


print "Swaroop's address is %s" % ab['Swaroop']


# Adding a key/value pair
ab['Guido'] = '[email protected]'


# Deleting a key/value pair
del ab['Spammer']


print '\nThere are %d contacts in the address-book\n' % len(ab)
for name, address in ab.items():
    print 'Contact %s at %s' % (name, address)


if 'Guido' in ab: # OR ab.has_key('Guido')
    print "\nGuido's address is %s" % ab['Guido'] 

输出:

Swaroop's address is [email protected]


There are 4 contacts in the address-book


Contact Swaroop at [email protected]
Contact Matsumoto at [email protected]
Contact Larry at [email protected]
Contact Guido at [email protected]


Guido's address is [email protected]


序列


真是不看不知道,一看没什么大不了
看例子吧,肯定能懂,但是要看仔细哦,很容易被阴到的
代码:

shoplist = ['apple', 'mango', 'carrot', 'banana']


# Indexing or 'Subscription' operation
print 'Item 0 is', shoplist[0]
print 'Item 1 is', shoplist[1]
print 'Item 2 is', shoplist[2]
print 'Item 3 is', shoplist[3]
print 'Item -1 is', shoplist[-1]
print 'Item -2 is', shoplist[-2]


# Slicing on a list
print 'Item 1 to 3 is', shoplist[1:3]
print 'Item 2 to end is', shoplist[2:]
print 'Item 1 to -1 is', shoplist[1:-1]
print 'Item start to end is', shoplist[:]


# Slicing on a string
name = 'swaroop'
print 'characters 1 to 3 is', name[1:3]
print 'characters 2 to end is', name[2:]
print 'characters 1 to -1 is', name[1:-1]
print 'characters start to end is', name[:] 




输出:

Item 0 is apple
Item 1 is mango
Item 2 is carrot
Item 3 is banana
Item -1 is banana
Item -2 is carrot
Item 1 to 3 is ['mango', 'carrot']
Item 2 to end is ['carrot', 'banana']
Item 1 to -1 is ['mango', 'carrot']
Item start to end is ['apple', 'mango', 'carrot', 'banana']
characters 1 to 3 is wa
characters 2 to end is aroop
characters 1 to -1 is waroo
characters start to end is swaroop 


shoplist[1:3]返回从位置1开始,包括位置2,但是停止在位置3的一个序列切片,因此返回一个含有两个项目的切片。类似地,shoplist[:]返回整个序列的拷贝。


参考

 

很显然翻译的这个参考这个词,太不合适了。
这是因为这里主要讲的是序列的赋值和引用问题
当使用赋值操作的时候只是引用,两个序列指向同一片内存地址
也就是说列表的赋值语句不创建拷贝内存。你得使用切片操作符来建立序列的内存的拷贝。
代码:

print 'Simple Assignment'
shoplist = ['apple', 'mango', 'carrot', 'banana']
mylist = shoplist # mylist is just another name pointing to the same object!


del shoplist[0]


print 'shoplist is', shoplist
print 'mylist is', mylist
# notice that both shoplist and mylist both print the same list without
# the 'apple' confirming that they point to the same object


print 'Copy by making a full slice'
mylist = shoplist[:] # make a copy by doing a full slice
del mylist[0] # remove first item


print 'shoplist is', shoplist
print 'mylist is', mylist
# notice that now the two lists are different 



输出:

$ python reference.py
Simple Assignment
shoplist is ['mango', 'carrot', 'banana']
mylist is ['mango', 'carrot', 'banana']
Copy by making a full slice
shoplist is ['mango', 'carrot', 'banana']
mylist is ['carrot', 'banana'] 


更多字符串的内容


你在程序中使用的字符串都是str类的对象。这个类的一些有用的方法会在下面这个例子中说明。如果要了解这些方法的完整列表,请参见help(str)。
代码:

# Filename: str_methods.py


name = 'Swaroop' # This is a string object 


if name.startswith('Swa'):
    print 'Yes, the string starts with "Swa"'


if 'a' in name:
    print 'Yes, it contains the string "a"'


if name.find('war') != -1:
    print 'Yes, it contains the string "war"'


delimiter = '_*_'
mylist = ['Brazil', 'Russia', 'India', 'China']
print delimiter.join(mylist) 



输出:

$ python str_methods.py
Yes, the string starts with "Swa"
Yes, it contains the string "a"
Yes, it contains the string "war"
Brazil_*_Russia_*_India_*_China 

 



第11章 面向对象的编程

 

self


类的方法与普通的函数只有一个特别的区别——它们必须有一个额外的第一个参数名称
假如你有一个类称为MyClass和这个类的一个实例MyObject。当你调用这个对象的方法MyObject.method(arg1, arg2)的时候,这会由Python自动转为MyClass.method(MyObject, arg1, arg2)——这就是self的原理了。


这也意味着如果你有一个不需要参数的方法,你还是得给这个方法定义一个self参数。

 


代码:

class Person:
'''Represents a person.'''
population=0


def __init__(self,name):
'''Initializes the person's data.'''
self.name=name
print '(Initializing %s)' %self.name


#When this person is created, he/she adds to the population
Person.population+=1

def __del__(self):
'''I am dying.'''
print '%s says bye.' %self.name


Person.population-=1


if Person.population==0:
print 'I am the last one.'
else:
print 'There are still %d people left.' %Person.population

def sayHi(self):
'''Greeting by the person.


Really, that's all it does.'''
print 'Hi, my name is %s.' %self.name

def howMany(self):
'''Prints the current population.'''
if Person.population==1:
print 'I am the only person here.'
else:
print 'We have %d persons here.' %Person.population


swaroop=Person('Swaroop')
swaroop.sayHi()
swaroop.howMany()


kalam=Person('Abdul Kalam')
kalam.sayHi()
kalam.howMany()


del kalam
swaroop.sayHi()
swaroop.howMany()


输出:

>>> 
(Initializing Swaroop)
Hi, my name is Swaroop.
I am the only person here.
(Initializing Abdul Kalam)
Hi, my name is Abdul Kalam.
We have 2 persons here.
Abdul Kalam says bye.
There are still 1 people left.
Hi, my name is Swaroop.
I am the only person here.
>>> 



其中Person.population += 1 是类的变量
__init__在开始时调用
__del__在对象被删除时调用


给C++/Java/C#程序员的注释
Python中所有的类成员(包括数据成员)都是 公共的 ,所有的方法都是 有效的 。
只有一个例外:如果你使用的数据成员名称以 双下划线前缀 比如__privatevar,Python的名称管理体系会有效地把它作为私有变量。
这样就有一个惯例,如果某个变量只想在类或对象中使用,就应该以单下划线前缀。而其他的名称都将作为公共的,可以被其他类/对象使用。记住这只是一个惯例,并不是Python所要求的(与双下划线前缀不同)。
同样,注意__del__方法与 destructor 的概念类似。

 

继承


概念已经很熟悉了
看一下例子吧,另外还支持多重继承。
代码:

class SchoolMember:
    '''Represents any school member.'''
    def __init__(self, name, age):
        self.name = name
        self.age = age
        print '(Initialized SchoolMember: %s)' % self.name


    def tell(self):
        '''Tell my details.'''
        print 'Name:"%s" Age:"%s"' % (self.name, self.age),


class Teacher(SchoolMember):
    '''Represents a teacher.'''
    def __init__(self, name, age, salary):
        SchoolMember.__init__(self, name, age)
        self.salary = salary
        print '(Initialized Teacher: %s)' % self.name


    def tell(self):
        SchoolMember.tell(self)
        print 'Salary: "%d"' % self.salary


class Student(SchoolMember):
    '''Represents a student.'''
    def __init__(self, name, age, marks):
        SchoolMember.__init__(self, name, age)
        self.marks = marks
        print '(Initialized Student: %s)' % self.name


    def tell(self):
        SchoolMember.tell(self)
        print 'Marks: "%d"' % self.marks


t = Teacher('Mrs. Shrividya', 40, 30000)
s = Student('Swaroop', 22, 75)


print # prints a blank line


members = [t, s]
for member in members:
    member.tell() # works for both Teachers and Students 



输出:

(Initialized SchoolMember: Mrs. Shrividya)
(Initialized Teacher: Mrs. Shrividya)
(Initialized SchoolMember: Swaroop)
(Initialized Student: Swaroop)


Name:"Mrs. Shrividya" Age:"40" Salary: "30000"
Name:"Swaroop" Age:"22" Marks: "75" 



一个术语的注释——如果在继承元组中列了一个以上的类,那么它就被称作 多重继承 。


第12章 输入/输出

 

文件


这里只是讲了讲最基本的操作,实际上,读读写写呗。最关键还是要学会使用help(file)来查找自己不知道的事。
代码:

poem = '''\
Programming is fun
When the work is done
if you wanna make your work also fun:
        use Python!
'''


f = file('poem.txt', 'w') # open for 'w'riting
f.write(poem) # write text to file
f.close() # close the file


f = file('poem.txt')
# if no mode is specified, 'r'ead mode is assumed by default
while True:
    line = f.readline()
    if len(line) == 0: # Zero length indicates EOF
        break
    print line,
    # Notice comma to avoid automatic newline added by Python
f.close() # close the file 
输出:
$ python using_file.py
Programming is fun
When the work is done
if you wanna make your work also fun:
        use Python! 

 


 

储存器


Python提供一个标准的模块,称为pickle。使用它你可以在一个文件中储存任何Python对象,之后你又可以把它完整无缺地取出来。这被称为 持久地 储存对象。
还有另一个模块称为cPickle,它的功能和pickle模块完全相同,只不过它是用C语言编写的,因此要快得多(比pickle快1000倍)。你可以使用它们中的任一个,而我们在这里将使用cPickle模块。记住,我们把这两个模块都简称为pickle模块。


代码:

import cPickle as p
#import pickle as p


shoplistfile = 'shoplist.data'
# the name of the file where we will store the object


shoplist = ['apple', 'mango', 'carrot']


# Write to the file
f = file(shoplistfile, 'w')
p.dump(shoplist, f) # dump the object to a file
f.close()


del shoplist # remove the shoplist


# Read back from the storage
f = file(shoplistfile)
storedlist = p.load(f)
print storedlist 



输出:

['apple', 'mango', 'carrot'] 



首先,请注意我们使用了import..as语法。这是一种便利方法,以便于我们可以使用更短的模块名称。在这个例子中,它还让我们能够通过简单地改变一行就切换到另一个模块(cPickle或者pickle)!在程序的其余部分的时候,我们简单地把这个模块称为p。


我们使用pickle模块的load函数的返回来取回对象。这个过程称为 取储存 。


第13章 异常

 

 try..except


处理异常
我们可以使用try..except语句来处理异常。我们把通常的语句放在try-块中,而把我们的错误处理语句放在except-块中。


代码:

import sys


try:
    s = raw_input('Enter something --> ')
except EOFError:
    print '\nWhy did you do an EOF on me?'
    sys.exit() # exit the program
except:
    print '\nSome error/exception occurred.'
    # here, we are not exiting the program


print 'Done' 



输出:

Enter something -->
Why did you do an EOF on me?


$ python try_except.py
Enter something --> Python is exceptional!
Done


我在windows下弄不出那个EOFError的错误,应该在linux平台下的ctrl+D


我们把所有可能引发错误的语句放在try块中,然后在except从句/块中处理所有的错误和异常。except从句可以专门处理单一的错误或异常,或者一组包括在圆括号内的错误/异常。如果没有给出错误或异常的名称,它会处理 所有的 错误和异常。对于每个try从句,至少都有一个相关联的except从句。


你还可以让try..catch块关联上一个else从句。当没有异常发生的时候,else从句将被执行。

引发异常

你可以使用raise语句 引发 异常。你还得指明错误/异常的名称和伴随异常 触发的 异常对象。你可以引发的错误或异常应该分别是一个Error或Exception类的直接或间接导出类。


代码:

class ShortInputException(Exception):
    '''A user-defined exception class.'''
    def __init__(self, length, atleast):
        Exception.__init__(self)
        self.length = length
        self.atleast = atleast


try:
    s = raw_input('Enter something --> ')
    if len(s) < 3:
        raise ShortInputException(len(s), 3)
    # Other work can continue as usual here
except EOFError:
    print '\nWhy did you do an EOF on me?'
except ShortInputException, x:
    print 'ShortInputException: The input was of length %d, \
          was expecting at least %d' % (x.length, x.atleast)
else:
    print 'No exception was raised.' 


输出:

Enter something -->
Why did you do an EOF on me?


$ python raising.py
Enter something --> ab
ShortInputException: The input was of length 2, was expecting at least 3


$ python raising.py
Enter something --> abc
No exception was raised. 


try..finally


假如你在读一个文件的时候,希望在无论异常发生与否的情况下都关闭文件,该怎么做呢?这可以使用finally块来完成
代码:

import time


try:
    f = file('poem.txt')
    while True: # our usual file-reading idiom
        line = f.readline()
        if len(line) == 0:
            break
        time.sleep(2)
        print line,
finally:
    f.close()
    print 'Cleaning up...closed the file' 



中途用Ctrl-c来中断程序。


第14章

 

Python标准库


讲了sys模块 和os模块
恐怕暂时对我的程序没什么作用。
比如:os模块
这个模块包含普遍的操作系统功能。如果你希望你的程序能够与平台无关的话,这个模块是尤为重要的。即它允许一个程序在编写后不需要任何改动,也不会发生任何问题,就可以在Linux和Windows下运行。


第15章 更多Python的内容

 

特殊的方法


这些都是类似于构造方法和析构方法一样的回调方法。
表15.1 一些特殊的方法

 

名称 说明
__init__(self,...) 这个方法在新建对象恰好要被返回使用之前被调用。
__del__(self) 恰好在对象要被删除之前调用。
__str__(self) 在我们对对象使用print语句或是使用str()的时候调用。
__lt__(self,other) 当使用 小于 运算符(<)的时候调用。类似地,对于所有的运算符(+,>等等)都有特殊的方法。
__getitem__(self,key) 使用x[key]索引操作符的时候调用。
__len__(self) 对序列对象使用内建的len()函数的时候调用。

 


列表综合


刚开始这个东西让我很痛苦呀
通过列表综合,可以从一个已有的列表导出一个新的列表。例如,你有一个数的列表,而你想要得到一个对应的列表,使其中所有大于2的数都是原来的2倍。对于这种应用,列表综合是最理想的方法。
代码:

listone = [2, 3, 4]
listtwo = [2*i for i in listone if i > 2]
print listtwo 


输出:

$ python list_comprehension.py
[6, 8]


这里我们为满足条件(if i > 2)的数指定了一个操作(2*i),从而导出一个新的列表。注意原来的列表并没有发生变化。在很多时候,我们都是使用循环来处理列表中的每一个元素,而使用列表综合可以用一种更加精确、简洁、清楚的方法完成相同的工作。


在函数中接收元组和列表


当要使函数接收元组或字典形式的参数的时候,有一种特殊的方法,它分别使用*和**前缀。这种方法在函数需要获取可变数量的参数的时候特别有用。
代码:

>>> def powersum(power, *args):
...     '''Return the sum of each argument raised to specified power.'''
...     total = 0
...     for i in args:
...          total += pow(i, power)
...     return total
...
>>> powersum(2, 3, 4)
25


>>> powersum(2, 10)
100 


由于在args变量前有*前缀,所有多余的函数参数都会作为一个元组存储在args中。如果使用的是**前缀,多余的参数则会被认为是一个字典的键/值对。


lambda形式


这个玩意好像没什么意思呀。
lambda语句被用来创建新的函数对象,并且在运行时返回它们。


代码:

def make_repeater(n):
    return lambda s: s*n


twice = make_repeater(2)


print twice('word')
print twice(5) 


输出:

$ python lambda.py
wordword
10 



汗水,这个东西很高级呀
再看,第一次调用make_repeater(2)返回了一个函数,这个函数的名字叫twice,很显然再给twice传值进去,是make_repeater里面的s部分。


exec和eval语句


exec语句用来执行储存在字符串或文件中的Python语句。例如,我们可以在运行时生成一个包含Python代码的字符串,然后使用exec语句执行这些语句。下面是一个简单的例子。
代码:

>>> exec 'print "Hello World"'
Hello World 



eval语句用来计算存储在字符串中的有效Python表达式。下面是一个简单的例子。

>>> eval('2*3')
6 


assert语句


assert语句用来声明某个条件是真的。例如,如果你非常确信某个你使用的列表中至少有一个元素,而你想要检验这一点,并且在它非真的时候引发一个错误,那么assert语句是应用在这种情形下的理想语句。当assert语句失败的时候,会引发一个AssertionError。
为什么直接用if?


代码:

>>> mylist = ['item']
>>> assert len(mylist) >= 1
>>> mylist.pop()
'item'
>>> assert len(mylist) >= 1
Traceback (most recent call last):
  File "", line 1, in ?
AssertionError 

 

repr函数

 


为什么会有这么多觉得很有趣的东西?
repr函数用来取得对象的规范字符串表示。反引号(也称转换符)可以完成相同的功能。注意,在大多数时候有eval(repr(object)) == object。
代码:

>>> i = []
>>> i.append('item')
>>> `i`
"['item']"
>>> repr(i)
"['item']" 


基本上,repr函数和反引号用来获取对象的可打印的表示形式。你可以通过定义类的__repr__方法来控制你的对象在被repr函数调用的时候返回的内容。


 

探索更多内容

 

  1. 基本知识学完了,还有一个拓展阅读,我觉得也挺有用的。
    Python标准库是一个丰富的库,在大多数时候,你可以在这个库中找到你所需的东西。这被称为Python的“功能齐全”理念。我强烈建议你在开始开发大型Python程序之前浏览一下Python标准文档。
  2. Python.org——Python编程语言的官方主页。你可以在上面找到Python语言和解释器的最新版本。另外还有各种邮件列表活跃地讨论Python的各方面内容。
  3. comp.lang.python是讨论Python语言的世界性新闻组。你可以把你的疑惑和询问贴在这个新闻组上。可以使用Google群在线访问这个新闻组,或加入作为新闻组镜像的邮件列表。
  4. 《Python实用大全》是一个极有价值的秘诀和技巧集合,它帮助你解决某些使用Python的问题。这是每个Python用户必读的一本书。
  5. 《迷人的Python》是David Mertz编著的一系列优秀的Python相关文章。
  6. 《深入理解Python》是给有经验的Python程序员的一本很优秀的书。如果你已经完整地阅读了本书,那么我强烈建议你接下来阅读《深入理解Python》。它覆盖了包括XML处理、单元测试和功能性编程在内的广泛的主题。
  7. Jython是用Java语言实现的Python解释器。这意味着你可以用Python语言编写程序而同时使用Java库!Jython是一个稳定成熟的软件。如果你也是一个Java程序员,我强烈建议你尝试一下Jython。
  8. IronPython是用C#语言实现的Python解释器,可以运行在.NET、Mono和DotGNU平台上。这意味着你可以用Python语言编写程序而使用.NET库以及其他由这三种平台提供的库!IronPython还只是一个前期alpha测试软件,现在还只适合用来进行试验。Jim Hugunin,IronPython的开发者,已经加入了微软公司,将在将来全力开发一个完整版本的IronPython。
  9. Lython是Python语言的Lisp前段。它类似于普通的Lisp语言,会被直接编译为Python字节码,这意味着它能与我们普通的Python代码协同工作。
  10. 另外还有很多很多的Python资源。其中比较有趣的有Daily Python-URL!,它使你保持与Python的最新进展同步。另外还有Vaults of Parnassus、ONLamp.com Python DevCenter、dirtSimple.org、Python Notes等等。

 

 

你可能感兴趣的:(python)