以下内容大部分出自《core python programming》
若被视为侵权
我会立即删除
1.1 程序输出,print 语句及“Hello World!”
有些语言, 比如 C, 通过函数输出数据到屏幕,例如函数printf()。然而在Python 和大多数解释执行的脚本语言,使用语句进行输出。很多的shell 脚本语言使用echo 命令来输出程
序结果。
核心笔记:在交互式解释器中显示变量的值
通常当你想看变量内容时,你会在代码中使用print 语句输出。不过在交互式解释器中,你可以用 print 语句显示变量的字符串表示,或者仅使用变量名查看该变量的原始值。
在下面的例子中,我们把一个字符串赋值给变量myString,先用print 来显示变量的内容,之后用变量名称来显示。
>>> myString = 'Hello World!'
>>> print myString
Hello World!
>>> myString
'Hello World!'
注意:在仅用变量名时,输出的字符串是被用单引号括起来了的。这是为了让非字符串对象也能以字符串的方式显示在屏幕上--即它显示的是该对象的字符串表示,而不仅仅是字符
串本身。引号表示你刚刚输入的变量的值是一个字符串。等你对Python 有了较深入的了解之后,你就知道print 语句调用str()函数显示对象,而交互式解释器则调用repr()函数来显示对象。
>>>a = 1
>>>a
1
注意两程序的区别。
1.2程序输入和raw_input()内建函数
下划线(_)在解释器中有特别的含义,表示最后一个表达式的值。所以上面的代码执行之后,下划线变量会包含字符串:
>>> _
Hello World!
Python 的print 语句,与字符串格式运算符( % )结合使用,可实现字符串替换功能,这一点和 C 语言中的printf()函数非常相似:
>>> print "%s is number %d!" % ("Python", 1)
Python is number 1!
%s 表示由一个字符串来替换,而%d 表示由一个整数来替换,另外一个很常用的就是%f, 它表示由一个浮点数来替换。我们会在本章中看到更多类似的例子。Python 非常灵活,所以即使
你将数字传递给 %s,也不会像其他要求严格的语言一样引发严重后果。参阅章节6.4.1 以了解更多关于字符串格式运算符的信息。Print 语句也支持将输出重定向到文件。这个特性是从Python2.0 开始新增的。符号 >> 用来重定向输出,下面这个例子将输出重定向到标准错误输出:
import sys
print >> sys.stderr, 'Fatal error: invalid input!'
import sys
print >> sys.stderr, 'Fatal error: invalid input!'
下面是一个将输出重定向到日志文件的例子:
logfile = open('/tmp/mylog.txt', 'a')
print >> logfile, 'Fatal error: invalid input!'
logfile.close()
从用户那里得到数据输入的最容易的方法是使用raw_input()内建函数。 它读取标准输入,并将读取到的数据赋值给指定的变量。 你可以使用 int() 内建函数将用户输入的字符串转换
为整数。
注意 这里的意思是你要输入数字 然后通过int()可以转化为整数,若你输入的是非数字,然后用int()会产生错误。
>>> user = raw_input('Enter login name: ')
Enter login name: root
>>> num = raw_input('Now enter a number: ')
Now enter a number: 1024
>>> print 'Doubling your number: %d' % (int(num) * 2)
Doubling your number: 2048
核心笔记:从交互式解释器中获得帮助
在学习 Python 的过程中,如果需要得到一个生疏函数的帮助,只需要对它调用内建函数help()。通过用函数名作为 help()的参数就能得到相应的帮助信息:
>>> help(raw_input)
Help on built-in function raw_input in module __builtin__:
raw_input(...)
raw_input([prompt]) -> string
1.3 注释
和大部分脚本及Unix-shell 语言一样,Python 也使用 # 符号标示注释,从 # 开始,直到一行结束的内容都是注释。
>>> # one comment
... print 'Hello World!' # another comment
Hello World!
有一种叫做文档字符串的特别注释。你可以在模块、类或者函数的起始添加一个字符串,起到在线文档的功能,这是Java 程序员非常熟悉的一个特性。
def foo():
"This is a doc string."
return True
与普通注释不同,文档字符串可以在运行时访问,也可以用来自动生成文档。(这句没看懂,自动生成文档)
2.4 运算符
和其他绝大多数的语言一样,Python 中的标准算术运算符以你熟悉的方式工作
+ - * / // % **
加、减、乘、除和取余都是标准运算符。Python 有两种除法运算符,单斜杠用作传统除法,双斜杠用作浮点除法(对结果进行四舍五入)。传统除法是指如果两个操作数都是整数的话,
它将执行是地板除(取比商小的最大整数)(关于“地板除”请参考第5 章——译者注),而浮点除法是真正的除法,不管操作数是什么类型,浮点除法总是执行真正的除法。你可以在第五
章(数字)学到更多有关传统除法、真正的除法及浮点除法的知识。
还有一个乘方运算符, 双星号(**)。尽管我们一直强调这些运算符的算术本质, 但是请注意对于其它数据类型,有些运算符是被重载了,比如字符串和列表。。让我们看一个例子
>>> print -2 * 4 + 3 ** 2
就象你看到的, 运算符的优先级和你想象的一样: + 和 - 优先级最低, *, /, //, %优先级较高, 单目运算符 + 和 - 优先级更高, 乘方的优先级最高。(3 ** 2) 首先求值, 然
后是 (-2 * 4), 然后是对两个结果进行求和。Python 当然也有标准比较运算符, 比较运算根据表达式的值的真假返回布尔值:
< <= > >= == != <>
试一试,看看这些比较运算会得到什么结果:
>>> 2 < 4
True
>>> 2 == 4
False
>>> 2 > 4
False
>>> 6.2 <= 6
False
>>> 6.2 <= 6.2
True
>>> 6.2 <= 6.20001
True
Python 目前支持两种“不等于”比较运算符, != 和 <> , 分别是C 风格和ABC/Pascal风格。目前后者慢慢地被淘汰了, 所以我们推荐使用前者。
Python 也提供了逻辑运算符:
and or not
使用逻辑运算符可以将任意表达式连接在一起,并得到一个布尔值:
>>> 2 < 4 and 2 == 4
False
>>> 2 > 4 or 2 < 4
True
>>> not 6.2 <= 6
True
>>> 3 < 4 < 5
True
python 支持这种这样的表达式
核心风格: 合理使用括号增强代码的可读性,在很多场合使用括号都是一个好主意,而没用括号的话,会使程序得到错误结果,或使代码可读性降低,引起阅读者困惑。。括号在Python
语言中不是必须存在的, 不过为了可读性, 使用括号总是值得的。任何维护你代码的人会感谢你, 在你再次阅读自己的代码时,你也会感谢你自己。
1.5 变量和赋值
Python 中变量名规则与其它大多数高级语言一样, 都是受C 语言影响(或者说这门语言本身就是C 语言写成的)。变量名仅仅是一些字母开头的标识符--所谓字母开头--意指大
写或小写字母,另外还包括下划线( _ ). 其它的字符可以是数字,字母, 或下划线。Python变量名是大小写敏感的, 也就是说变量 "cAsE" 与 "CaSe" 是两个不同的变量。
Python 是动态类型语言, 也就是说不需要预先声明变量的类型。 变量的类型和值在赋值那一刻被初始化。变量赋值通过等号来执行。
>>> counter = 0
>>> miles = 1000.0
>>> name = 'Bob'
>>> counter = counter + 1
>>> kilometers = 1.609 * miles
>>> print '%f miles is the same as %f km' % (miles, kilometers)
1000.000000 miles is the same as 1609.000000 km
上面是五个变量赋值的例子。第一个是整数赋值,第二个是浮点数赋值,第三个是字符串赋值,第四个是对一个整数增1, 最后一个是浮点乘法赋值。
Python 也支持增量赋值,也就是运算符和等号合并在一起, 看下面的例子:
n = n * 10
将上面的例子改成增量赋值方式就是:
n *= 10
Python 不支持C 语言中的自增1 和自减1 运算符, 这是因为 + 和 - 也是单目运算符,
Python 会将 --n 解释为-(-n) 从而得到 n , 同样 ++n 的结果也是 n.
2.6数字
Python 支持五种基本数字类型,其中有三种是整数类型。
? int (有符号整数)
? long (长整数)
? bool (布尔值)
? float (浮点值)
? complex (复数)
下面是一些例子:Python 中有两种有趣的类型是 Python 的长整型和复数类型。请不要将Python 的长整数与C 语言的长整数混淆。Python 的长整数所能表达的范围远远超过C 语言的长整数, 事实上,Python 长整数仅受限于用户计算机的虚拟内存总数。如果你熟悉 Java, Python 的长整数类似于 Java 中的BigInteger 类型。
从长远来看, 整型与长整型正在逐步统一为一种整数类型。从Python2.3 开始,再也不会报整型溢出错误, 结果会自动的被转换为长整数。在未来版本的Python 中, 两种整数类型将会无缝结合, 长整数后缀 “L”也会变得可有可无。
布尔值是特殊的整数。 尽管布尔值由常量 True 和 False 来表示, 如果将布尔值放到一个数值上下文环境中(比方将 True 与一个数字相加), True 会被当成整数值 1, 而False
则会被当成整数值 0。 复数(包括-1 的平方根, 即所谓的虚数)在其它语言中通常不被直接支持(一般通过类来实现)。
其实还有第六种数字类型, decimal, 用于十进制浮点数。不过它并不是内建类型, 你必须先导入 decimal 模块才可以使用这种数值类型。 由于需求日渐强烈, Python 2.4 增加
了这种类型。举例来说, 由于在二进制表示中有一个无限循环片段,数字1.1 无法用二进制浮点数精确表示。因此, 数字1.1 实际上会被表示成:
>>> 1.1
1.1000000000000001
>>> print decimal.Decimal('1.1')
1.1
第五章详细将介绍所有的数字类型
1.7字符串
Python 中字符串被定义为引号之间的字符集合。Python 支持使用成对的单引号或双引号,三引号(三个连续的单引号或者双引号)可以用来包含特殊字符。使用索引运算符( [ ] )和切
片运算符( [ : ] )可以得到子字符串。字符串有其特有的索引规则:第一个字符的索引是 0,最后一个字符的索引是 -1,加号( + )用于字符串连接运算,星号( * )则用于字符串重复。下面是几个例子:
>>> pystr = 'Python'
>>> iscool = 'is cool!'
>>> pystr[0]
'P'
>>> pystr[2:5]
'tho'
>>> iscool[:2]
'is'
>>> iscool[3:]
'cool!'
>>> iscool[-1]
'!'
>>> pystr + iscool
'Pythonis cool!'
>>> pystr + ' ' + iscool
'Python is cool!'
>>> pystr * 2
'PythonPython'
>>> '-' * 20
'--------------------'
>>> pystr = '''python
... is cool'''
>>> pystr
'python\nis cool'
>>> print pystr
python
is cool
>>>
你可以在第六章学到更多有关字符串的知识。
1.8 列表和元组
可以将列表和元组当成普通的“数组”,它能保存任意数量任意类型的Python 对象。和数组一样,通过从0 开始的数字索引访问元素,但是列表和元组可以存储不同类型的对象。
列表和元组有几处重要的区别。列表元素用中括号( [ ])包裹,元素的个数及元素的值可以改变。元组元素用小括号(( ))包裹,不可以更改(尽管他们的内容可以)。元组可以看成是只读的列表。通过切片运算( [ ] 和 [ : ] )可以得到子集,这一点与字符串的使用方法一样。
>>> aList = [1, 2, 3, 4]
>>> aList
[1, 2, 3, 4]
>>> aList[0]
1
>>> aList[2:]
[3, 4]
>>> aList[:3]
[1, 2, 3]
>>> aList[1] = 5
>>> aList
[1, 5, 3, 4]
元组也可以进行切片运算,得到的结果也是元组(不能被修改):
>>> aTuple = ('robots', 77, 93, 'try')
>>> aTuple
('robots', 77, 93, 'try')
>>> aTuple[:3]
('robots', 77, 93)
>>> aTuple[1] = 5
Traceback (innermost last):
File "<stdin>", line 1, in ?
TypeError: object doesn't support item assignment
1.9 字典
字典是Python 中的映射数据类型,工作原理类似Perl 中的关联数组或者哈希表,由键-值(key-value)对构成。几乎所有类型的Python 对象都可以用作键,不过一般还是以数字或者
字符串最为常用。
值可以是任意类型的Python 对象,字典元素用大括号({ })包裹。
可以在第六章学到更多有关列表、元组以及字符串的知识。
>>> aDict = {'host': 'earth'} # create dict
>>> aDict['port'] = 80 # add to dict
>>> aDict
{'host': 'earth', 'port': 80}
>>> aDict.keys()
['host', 'port']
>>> aDict['host']
'earth'
>>> for key in aDict:
... print key, aDict[key]
...
host earth
port 80
在第七章中会详细讲解字典。
1.10 代码块及缩进对齐
代码块通过缩进对齐表达代码逻辑而不是使用大括号,因为没有了额外的字符,程序的可读性更高。而且缩进完全能够清楚地表达一个语句属于哪个代码块。当然,代码块也可以只有
一个语句组成。
对一个Python 初学者来说, 仅使用缩进可能令他诧异。 人们通常竭力避免改变, 因此对那些使用大括号很多老年人来说, 初次使用纯缩进来表示逻辑也许会多少感到有些不够坚定。
(不用大括号?到底成不成啊?)。然而回想一下, python 有两大特性, 一是简洁,二是可读性好。如果你实在讨厌使用缩进作为代码分界, 我们希望你从现在开始,半年后再来看一下
这种方式。也许你会发现生活中没有大括号并不会象你想像的那么糟糕。
11.1 if 语句
标准if 条件语句的语法如下:
if expression:
if_suite
如果表达式的值非0 或者为布尔值True, 则代码组 if_suite 被执行; 否则就去执行下一条语句。 代码组是一个Python 术语, 它由一条或多条语句组成,表示一个子代码块。Python与其它语言不同, 条件条达式并不需要用括号括起来。
if x < .0:
print '”x” must be atleast 0!'
Python 当然也支持 else 语句, 语法如下:
if expression:
if_suite
else:
else_suite
Python 还支持 elif (意指 “else-if ”)语句,语法如下:
if expression1:
if_suite
elif expression2:
elif_suite
else:
else_suite
在本书写作之时, 正在进行一个关于是否需要增加 switch/case 语句的讨论, 不过目前并没有什么实质性的进展。 在将来版本的Python 语言当中, 也非常有可能看到这样的“动
物”。 这个例子似乎有点奇怪、让人觉得困惑, 但是因为有了Python 干净的语法,if-elif-else 语句并不象别人说的那么丑陋(以致不能让人接受)。如果你非要避免写一堆if-elif-else 语句, 另一种变通的解决方案是使用for 循环(参阅2.13)来迭代你可能的"cases"列表。
在第8 章你可以学到更多有关 if, elif, else 条件语句的知识。
1.12 while 循环
标准while 条件循环语句的语法类似if. 再说一次, 要使用缩进来分隔每个子代码块。
while expression:
...while_suite
句 while_suite 会被连续不断的循环执行, 直到表达lse;式的值变成 0 或 Fa 接着python 会执行下一句代码。 类似if 语句, Python 的while 语句中的条件表达式也不需要用括号括起来。
>>> counter = 0
>>> while counter < 3:
... print 'loop #%d' % (counter)
... counter += 1
loop #0
loop #1
loop #2
while 循环和马上就要讲到的for 循环会在第8 章的循环一节进行详细讲解。
1.13 for 循环和range()内建函数
Python 中的for 循环与传统的for 循环(计数器循环)不太一样, 它更象shell 脚本里的foreach 迭代。Python 中的for 接受可迭代对象(例如序列或迭代器)作为其参数,每次迭代其中一个元素。
>>> print 'I like to use the Internet for:'
I like to use the Internet for:
>>> for item in ['e-mail', 'net-surfing', 'homework',
'chat']:
... print item
...
e-mail
net-surfing
homework
chat
上面例子的输出如果能在同一行就会美观许多。print 语句默认会给每一行添加一个换行符。只要在print 语句的最后添加一个逗号(,), 就可以改变它这种行为。
print 'I like to use the Internet for:'
for item in ['e-mail', 'net-surfing', 'homework', 'chat']:
print item,
上面的代码还添加了一个额外的没有任何参数的 print 语句, 它用来输出一个换行符。否则, 提示信息就会立刻出现在我们的输出之后。 下面是以上代码的输出:
I like to use the Internet for:
e-mail net-surfing homework chat
为了输出清晰美观, 带逗号的print 语句输出的元素之间会自动添加一个空格。通过指定输出格式, 程序员可以最大程度的控制输出布局, 也不用担心这些自动添加的空格。它也可以将所有数据放到一处输出--只需要将数据放在格式化运算符右侧的元组或字典中。
>>> who = 'knights'
>>> what = 'Ni!'
>>> print 'We are the', who, 'who say', what, what, what, what
We are the knights who say Ni! Ni! Ni! Ni!
>>> print 'We are the %s who say %s' % \
... (who, ((what + ' ') * 4))
We are the knights who say Ni! Ni! Ni! Ni!
使用字符串格式运算符还允许我们做一些字符串输出之前的整理工作, 就象你在刚才的例子中看到的一样。
通过演示一个让Python for 循环更象传统循环(换言之, 计数循环)的示例, 我们来结束对循环的介绍。因为我们不能改变 for 循环的行为(迭代一个序列), 我们可以生成一个数字序列。 这样, 尽管我们确实是在迭代一个序列, 但是它至少展示的是递增计数的效果。
>>> for eachNum in [0, 1, 2]:
... print eachNum
...
0
1
2
在这个循环中, eachNum 包含的整数值可以用于显示, 也可以用于计算。因为我们要使用的数值范围可能会经常变化,Python 提供了一个range()内建函数来生成这种列表。它正好能满足我们的需要, 接受一个数值范围, 生成一个列表。
>>> for eachNum in range(3):
... print eachNum
...
0
1
2
对字符串来说, 很容易迭代每一个字符。
>>> foo = 'abc'
>>> for c in foo:
... print c
...
a
b
c
range()函数经常和len()函数一起用于字符串索引。 在这里我们要显示每一个元素及其
索引值:
>>> foo = 'abc'
>>> for i in range(len(foo)):
... print foo[i], '(%d)' % i
...
a (0)
b (1)
c (2)
不过, 这些循环有一个约束, 你要么循环索引, 要么循环元素。这导致了enumerate()函数的推出(Python2.3 新增)。 它同时做到了这两点:
>>> for i, ch in enumerate(foo):
... print ch, '(%d)' % i
...
a (0)
b (1)
c (2)
1.13 列表解析
这是一个让人欣喜的术语, 表示你可以在一行中使用一个for 循环将所有值放到一个列表当中:
>>> squared = [x ** 2 for x in range(4)]
>>> for i in squared:
... print i
0
1
4
9
列表解析甚至能做更复杂的事情, 比如挑选出符合要求的值放入列表:
>>> sqdEvens = [x ** 2 for x in range(8) if not x % 2]
>>>
>>> for i in sqdEvens:
... print i
0
4
16
36
问 : 按照上面的例子 怎样在一行中写出将 10 以内的素数赋给一个列表?
1.15 文件和内建函数open() 、file()
在你已经习惯一门语言的语法之后, 文件访问是相当重要的一环。在一些工作做完之后,将它保存到持久存储是很重要的。
如何打开文件
handle = open(file_name, access_mode = 'r')
file_name 变量包含我们希望打开的文件的字符串名字, access_mode 中 'r' 表示读取,'w' 表示写入, 'a' 表示添加。其它可能用到的标声还有 '+' 表示读写, 'b'表示二进制访问. 如果未提供 access_mode , 默认值为 'r'。如果 open() 成功, 一个文件对象句柄会被返回。所有后续的文件操作都必须通过此文件句柄进行。当一个文件对象返回之后, 我们就可以访问它的一些方法, 比如 readlines() 和close().文件对象的方法属性也必须通过句点属性标识法访问(参阅下面的核心笔记)
核心笔记:什么是属性?
属性是与数据有关的项目, 属性可以是简单的数据值, 也可以是可执行对象, 比如函数和方法。哪些对象拥有属性呢? 很多。 类, 模块, 文件还有复数等等对象都拥有属性。
我如何访问对象属性? 使用句点属性标识法。 也就是说在对象名和属性名之间加一个句点: object.attribute
下面有一些代码, 提示用户输入文件名, 然后打开一个文件, 并显示它的内容到屏幕上:
filename = raw_input('Enter file name: ')
fobj = open(filename, 'r')
for eachLine in fobj:
print eachLine,
fobj.close()
我们的代码没有用循环一次取一行显示, 而是做了点改变。我们一次读入文件的所有行,然后关闭文件, 再迭代每一行输出。这样写代码的好处是能够快速完整的访问文件。内容输出和文件访问不必交替进行。这样代码更清晰, 而且将不相关的任务区分开来。需要注意的一点是文件的大小。 上面的代码适用于文件大小适中的文件。对于很大的文件来说, 上面的代码会占用太多的内存, 这时你最好一次读一行。(下一节有一个好例子)
我们的代码中另一个有趣的语句是我们又一次在print 语句中使用逗号来抑制自动生成的换行符号。 为什么要这样做?因为文件中的每行文本已经自带了换行字符, 如果我们不抑制print 语句产生的换行符号, 文本在显示时就会有额外的空行产生。
file()内建函数是最近才添加到Python 当中的。它的功能等同于 open(), 不过file()这个名字可以更确切的表明它是一个工厂函数。(生成文件对象)类似int()生成整数对象,dict()生成字典对象。在第9 章, 我们详细介绍文件对象, 及它们的内建方法属性, 以及如何访问本地文件系统。 请参考第9 章以了解详细信息。
1.16 错误和异常
编译时会检查语法错误, 不过 Python 也允许在程序运行时检测错误。当检测到一个错误,Python 解释器就引发一个异常, 并显示异常的详细信息。程序员可以根据这些信息迅速定位问题并进行调试, 并找出处理错误的办法。
要给你的代码添加错误检测及异常处理, 只要将它们封装在 try-except 语句当中。 try之后的代码组, 就是你打算管理的代码。 except 之后的代码组, 则是你处理错误的代码。
try:
filename = raw_input('Enter file name: ')
fobj = open(filename, 'r')
for eachLine in fobj:
print eachLine, fobj.close()
except IOError, e:
print 'file open error:', e
程序员也可以通过使用 raise 语句故意引发一个异常。在第10 章你可以学到更多有关Python 异常的知识。
1.17 函数
类似其它的语言, Python 中的函数使用小括号( () )调用。函数在调用之前必须先定义。如果函数中没有 return 语句, 就会自动返回 None 对象。
Python 是通过引用调用的。 这意味着函数内对参数的改变会影响到原始对象。不过事实上只有可变对象会受此影响, 对不可变对象来说, 它的行为类似按值调用。
如何定义函数
def function_name([arguments]):
"optional documentation string"
function_suite
定义一个函数的语法由 def 关键字及紧随其后的函数名再加上该函数需要的几个参数组成。函数参数(比较上面例子中的arguments)是可选的, 这也是为什么把它们放到中括号中的原因。(在你的代码里千万别写上中括号!)这个语句由一个冒号(:)结束(与if 和while语句的结束方式一样), 之后是代表函数体的代码组, 下面是一个简短的例子:
def addMe2Me(x):
'apply + operation to argument'
return (x + x)
这个函数, 干的是“在我的值上加我”的活。它接受一个对象, 将它的值加到自身, 然后返回和。对于数值类型参数, 它的结果是显而易见的, 不过我要在这里指出, 加号运算符几乎与所有数据类型工作。换句话说, 几乎所有的标准数据类型都支持 + 运算符, 不管是数值相加还是序列合并。
如何调用函数
>>> addMe2Me(4.25)
8.5
>>>
>>> addMe2Me(10)
20
>>>
>>> addMe2Me('Python')
'PythonPython'
>>>
>>> addMe2Me([-1, 'abc'])
[-1, 'abc', -1, 'abc']
Python 语言中调用函数与在其它高级语言中一样, 函数名加上函数运算符, 一对小括号。括号之间是所有可选的参数。即使一个参数也没有, 小括号也不能省略。注意一下, + 运算符在非数值类型中如何工作。
默认参数
函数的参数可以有一个默认值, 如果提供有默认值,在函数定义中, 参数以赋值语句的形式提供。事实上这仅仅是提供默认参数的语法,它表示函数调用时如果没有提供这个参数, 它就取这个值做为默认值。
>>> def foo(debug=True):
... 'determine if in debug mode with default argument'
... if debug:
... print 'in debug mode'
... print 'done'
...
>>> foo()
in debug mode
done
>>> foo(False)
done
1.18 类
类是面向对象编程的核心, 它扮演相关数据及逻辑的容器角色。它们提供了创建“真实”对象(也就是实例)的蓝图。因为Python 并不强求你以面向对象的方式编程(与Java 不同), 此刻你也可以不学习类。 不过我们还是在这儿放了些例子, 以方便感兴趣的读者浏览。
如何定义类
class ClassName(base_class[es]):
"optional documentation string"
static_member_declarations
method_declarations
使用 class 关键字定义类。 可以提供一个可选的父类或者说基类; 如果没有合适的基类,那就使用 object 作为基类。class 行之后是可选的文档字符串, 静态成员定义, 及方法定义。
class FooClass(object):
"""my very first class: FooClass"""
version = 0.1 # class (data) attribute
def __init__(self, nm='John Doe'):
"""constructor"""
self.name = nm # class instance (data) attribute
print 'Created a class instance for', nm
def showname(self):
"""display instance attribute and class name"""
print 'Your name is', self.name
print 'My name is', self.__class__.__name__
def showver(self):
"""display class(static) attribute"""
print self.version # references FooClass.version
def addMe2Me(self, x): # does not use 'self'
"""apply + operation to argument"""
return x + x
在上面这个类中, 我们定义了一个静态变量 version, 它将被所有实例及四个方法共享,__init__(), showname(), showver(), 及熟悉的 addMe2Me(). 这些 show*()方法并没有做什么有用的事情, 仅仅输出对应的信息。 __init__() 方法有一个特殊名字, 所有名字开始和结束都有两个下划线的方法都是特殊方法。
当一个类实例被创建时, __init__() 方法会自动执行, 在类实例创建完毕后执行, 类似构建函数。__init__() 可以被当成构建函数, 不过不象其它语言中的构建函数, 它并不创建实例--它仅仅是你的对象创建后执行的第一个方法。它的目的是执行一些该对象的必要的初始化工作。通过创建自己的 __init__() 方法, 你可以覆盖默认的 __init__()方法(默认的方法什么也不做),从而能够修饰刚刚创建的对象。在这个例子里, 我们初始化了一个名为 name的类实例属性(或者说成员)。这个变量仅在类实例中存在, 它并不是实际类本身的一部分。__init__()需要一个默认的参数, 前一节中曾经介绍过。毫无疑问,你也注意到每个方法都有
的一个参数, self.
什么是 self ? 它是类实例自身的引用。其他语言通常使用一个名为 this 的标识符。
如何创建类实例
>>> foo1 = FooClass()
Created a class instance for John Doe
屏幕上显示的字符串正是自动调用 __init__() 方法的结果。当一个实例被创建,__init__()就会被自动调用。不管这个__int__()是自定义的还是默认的。创建一个类实例就像调用一个函数, 它们确实拥有一样的语法。它们都是可调用对象。类实例使用同样的函数运算符调用一个函数或方法。既然我们成功创建了第一个类实例, 那现在来进行一些方法调用:
>>> foo1.showname() Your name is John Doe
My name is __main__.FooClass
>>>
>>> foo1.showver()
0.1
>>> print foo1.addMe2Me(5)
10
>>> print foo1.addMe2Me('xyz')
xyzxyz
每个方法的调用都返回我们期望的结果。比较有趣的数据是类名字。在showname()方法中,我们显示 self.__class__.__name__ 变量的值。对一个实例来说, 这个变量表示实例化它的类的名字。(self.__class__引用实际的类)。在我们的例子里, 创建类实例时我们并未传递名字参数, 因此默认参数 'John Doe' 就被自动使用。在我们下一个例子里, 我们将指定一个参数。
>>> foo2 = FooClass('Jane Smith') Created a class instance for Jane Smith
>>> foo2.showname()
Your name is Jane Smith
My name is FooClass
第十三章将详细介绍Python 类和类实例。
1.19 模块
模块是一种组织形式, 它将彼此有关系的Python 代码组织到一个个独立文件当中。模块可以包含可执行代码, 函数和类或者这些东西的组合。当你创建了一个 Python 源文件,模块的名字就是不带 .py 后缀的文件名。一个模块创建之后, 你可以从另一个模块中使用 import 语句导入这个模块来使用。如何导入模块
import module_name
如何访问一个模块函数或访问一个模块变量一旦导入完成, 一个模块的属性(函数和变量)可以通过熟悉的 .句点属性标识法访问。
module.function()
module.variable
现在我们再次提供 Hello World! 例子, 不过这次使用 sys 模块中的输出函数。
>>> import sys
>>> sys.stdout.write('Hello World!\n')
Hello World!
>>> sys.platform
'win32'
>>> sys.version
'2.4.2 (#67, Sep 28 2005, 10:51:12) [MSC v.1310 32 bit(Intel)]'
这些代码的输出与我们使用 print 语句完全相同。 唯一的区别在于这次调用了标准输出的 write()方法,而且这次需要显式的在字符串中提供换行字符, 不同于print 语句, write()不会自动在字符串后面添加换行符号。关于模块和导入, 你可以在第12 章中得到更多有用的信息。在那里会详细介绍本章上面所有提到的主题,希望我们提供的快速入门能达到你迅速使用Python 开始工作的目标。
核心笔记:什么是“PEP”?
在本书中你会经常看到 PEP 这个字眼。 一个 PEP 就是一个 Python 增强提案(PythonEnhancement Proposal), 这也是在新版Python 中增加新特性的方式。 从初学者的角度看,它们是一些高级读物, 它们不但提供了新特性的完整描述, 还有添加这些新特性的理由, 如果需要的话, 还会提供新的语法、 技术实现细节、向后兼容信息等等。在一个新特性被整合进Python 之前, 必须通过Python 开发社区, PEP 作者及实现者, 还有Python 的创始人, Guidovan Rossum(Python 终身的仁慈的独裁者)的一致同意。PEP1 阐述了PEP 的目标及书写指南。在PEP0 中可以找到所有的PEP。 PEP 索引的网址是: http://python.org/dev/peps.
1.19 实用的函数
本章中, 我们用到了很多实用的内建函数。我们在表1.1 中总结了这些函数, 并且提供了一些其它的有用函数。(注意我们并没有提供完整的使用语法,仅提供了我们认为可能对你有用的部分)
表1.1 对新Python 程序员有用的内建函数
函数 描述
dir([obj]) 显示对象的属性,如果没有提供参数, 则显示全局变量的名字
help([obj]) 以一种整齐美观的形式 显示对象的文档字符串, 如果没有提供任何参
数, 则会进入交互式帮助。
int(obj) 将一个对象转换为整数
len(obj) 返回对象的长度
open(fn, mode) 以 mode('r' = 读, 'w'= 写)方式打开一个文件名为 fn 的文件
range([[start,]stop[,step]) 返回一个整数列表。起始值为 start, 结束值为 stop - 1; start
默认值为 0, step默认值为1。
raw_input(str) 等待用户输入一个字符串, 可以提供一个可选的参数 str 用作提示信
息。
str(obj) 将一个对象转换为字符串
type(obj) 返回对象的类型(返回值本身是一个type 对象!)