在底下的例子里,你可以很容易区别凡是需要输入的地方都会出现prompts (">>
> " 或 "... "),凡是输出的结果则没有。如果你想要跟着这个教学文件一起做的话,你就得打入所有在prompts之后的指令,凡是没有prompts出现的行就是直译器输出的结果。值得注意的是,secondary
promt 之后如果什么东西都没有,表示这是一个空行(直接按ENTER的结果),也表示这是一个多行指令的结束。
在本文件中的大部分例子,都有加上注释,甚至是那些互动模式下的例子。注释(comment)在Python中是以 " #" 之后的东西都是注释(译:跟Perl一样)。注释可以自成一行,也可以跟在空白字元或是程式码的后面。但是,如果 " #" 是在字串常数(string literal)之中的话,就不代表注释的意义,而只是一个普通字元罢了。
底下是一些例子:
# this is the first comment
SPAM = 1 # and this is the second comment
# ... and now a third!
STRING = "# This is not a comment."
现在我们来试一试一些简单的Python指令吧。请先启动Python的直译器并且等待primary prompt( "
>>
> " )的出现。(应该不会很久的)
直译器就好像一个计算机一样:你可以打入一个表示式(expression),然后直译器会把这个expression的执行结果秀出来。Expression的语法都很简单直接,一般的运算符号
+
, -
, *
以及 /
的用法就跟其他的程式语言(像是Pascal或C)一样。你也可以用括号
"( )" 来表示运算执行的先后次序。例子如下:
>>> 2+2
4
>>> # This is a comment
... 2+2
4
>>> 2+2 # and a comment on the same line as code
4
>>> (50-5*6)/4
5
>>> # Integer division returns the floor:
... 7/3
2
>>> 7/-3
-3
跟C语言一样,等于符号 ("=") 其实是表示设定某个值给一个变数的意思。虽然设定 ("=") 运算本身是有结果值的,但是直译器并不会输出其结果来。
>>> width = 20
>>> height = 5*9
>>> width * height
900
一个值是可以同时设给许多变数的:
>>> x = y = z = 0 # Zero x, y and z
>>> x
0
>>> y
0
>>> z
0
浮点数的运算在Python里面也是支援的,如果整数与浮点数(带小数点或e的数)进行运算的话,整数部分会先转换(convert)成浮点数再进行运算。
>>> 4 * 2.5 / 3.3
3.0303030303
>>> 7.0 / 2
3.5
甚至连复数的运算也支援喔,只需要把虚数部分加上 "j" 或是 " J"在其后就可以了。如果实部不为零的话,复数的写法就写成 "(real+ imagj)" 。或者,我们也可以用函数的方式来表示复数为 "complex(real , imag)" 的形式。
>>> 1j * 1J
(-1+0j)
>>> 1j * complex(0,1)
(-1+0j)
>>> 3+1j*3
(3+3j)
>>> (3+1j)*3
(9+3j)
>>> (1+2j)/(1+1j)
(1.5+0.5j)
复数的虚数部分及实数部分的值都是以浮点数(float point numbers)来表示的,如果 z
代表一个复数的话,你可以很轻易的用 z.real
以及 z.imag
得到一个复数的实数部分及虚数部分。
>>> a=1.5+0.5j
>>> a.real
1.5
>>> a.imag
0.5
复数没有办法直接用 (float(),
int() 或是 long()) 转换成浮点数或是整数。事实上,复数没有直接对应的实数,你必须用
abs(z)
来得到 z
的magnitude(以浮点数表示),或是如上所述
用z.real
直接得到其实数部分。
>>> a=1.5+0.5j
>>> float(a)
Traceback (innermost last):
File "<stdin>", line 1, in ?
TypeError: can't convert complex to float; use e.g. abs(z)
>>> a.real
1.5
>>> abs(a)
1.58113883008
在互动模式之下,最后一个印出来的expression的值会储存在一个特殊变数 "_
" 之中。这表示,当你用Python的直译器来当作计算机用的时候,想要连续做运算其实是方便许多的。如下例:
>>> tax = 17.5 / 100
>>> price = 3.50
>>> price * tax
0.61249999999999993
>>> price + _
4.1124999999999998
>>> round(_, 2)
4.1100000000000003
对于使用者来说, "_
" 这个变数是一个唯读的变数。你没有办法设定一个值给它,当你这样做的时候,事实上你是重新创造一个同名的变数,但是跟之前系统内建的
"_
" 这个变数是一点关系也没有的了。
除了数字之外, Python也有能力处理字串(string)。字串在Python中有很多种表达方式,它可以放在双括号””之中,也可以放在单括号’’里面:
>>> 'spam eggs'
'spam eggs'
>>> 'doesn\'t'
"doesn't"
>>> "doesn't"
"doesn't"
>>> '"Yes," he said.'
'"Yes," he said.'
>>> "\"Yes,\" he said."
'"Yes," he said.'
>>> '"Isn\'t," she said.'
'"Isn\'t," she said.'
字串常数(string literals)是可以跨越多行的,其表示方法有很多。如果要换行的话可以用”\”符号来表示之。如下例:
hello = "This is a rather long string containing\n\
several lines of text just as you would do in C.\n\
Note that whitespace at the beginning of the line is\
significant.\n"
print hello
这个例子会印出以下的结果:
This is a rather long string containing
several lines of text just as you would do in C.
Note that whitespace at the beginning of the line is significant.
你也可以用成对的三个单引号( """
) 或双引号 (
'''
) 来表示字串。在此情况下你所打入的ENTER就会直接被解读为换行符号而不需要再用\n了。
print """
Usage: thingy [OPTIONS]
-h Display this usage message
-H hostname Hostname to connect to
"""
这个例子会印出以下的结果:
Usage: thingy [OPTIONS]
-h Display this usage message
-H hostname Hostname to connect to
如果你打入的expression是字串的运算,运算的结果的同样的会由直译器显示出来,而且显示的方式跟你直接打入字串常数(string literals)是一样的:会在引号之中,所有有escape character “\”表示的字元都会依样的显示出来。如果字串本身包含有单引号,整个字串就会用双引号括起来,要不然就会只用单引号来把整个字串括起来。(如果你使用 print 这个叙述(statement)来印出字串的话,萤幕的输出就不会有引号出现,而且字串中的escape character (\”表示的特殊字元) 都会显示出其所代表的意义来。)
字串可以用 +
这个运算元来相加 (连接起来),或是用
*
这个运算元来重复之。请看例子:
>>> word = 'Help' + 'A'
>>> word
'HelpA'
>>> '<' + word*5 + '>'
'<HelpAHelpAHelpAHelpAHelpA>'
如果你把两个字串常数放在一起,它们自动就会相加起来。所以,上面的例子的第一行也可以写作 "word = 'Help' 'A'" 。不过这个方法只适用于两个字串常数的相加,其他情况就不适合了。请看例子:
>>> import string
>>> 'str' 'ing' # <- This is ok
'string'
>>> string.strip('str') + 'ing' # <- This is ok
'string'
>>> string.strip('str') 'ing' # <- This is invalid
File "<stdin>", line 1
string.strip('str') 'ing'
^
SyntaxError: invalid syntax
如同在C语言一样,字串是有标记(subscript(index))的,第一个字元的标记(subscript(index))就是0。在Python中没有另外一个字元character资料型态,一个字元就是一个长度为 1的字串。就像是在Icon语言一样,字串是可以用其subscript(index)来切出( slice notation )其中的一部份的,其语法为 ""。
>>> word[4]
'A'
>>> word[0:2]
'He'
>>> word[2:4]
'lp'
与C不同的是,Python的字串是不可改变的(immutable),如果你想要改变其中的一个字元或是一个部份(slice),你会得到一个错误的信息:
>>> word[0] = 'x'
Traceback (innermost last):
File "<stdin>", line 1, in ?
TypeError: object doesn't support item assignment
>>> word[:-1] = 'Splat'
Traceback (innermost last):
File "<stdin>", line 1, in ?
TypeError: object doesn't support slice assignment
但是你可以任意使用一个字串的一个字元或是一个部份(slice)来创造出另一个字串,这是完全可行的:
>>> 'x' + word[1:]
'xelpA'
>>> 'Splat' + word[-1:]
'SplatA'
当你用字串切片(string slice)的语法时,可以使用其预定(default)的subscript(index)值,这是很方便的。第一个subscript(index)的预设值是0,第二个subscript(index)的预设值则是这个字串的整体长度。
>>> word[:2] # The first two characters
'He'
>>> word[2:] # All but the first two characters
'lpA'
所以, s[:i] + s[i:]
会恰好等于 s
。你可以想一想为什么:
>>> word[:2] + word[2:]
'HelpA'
>>> word[:3] + word[3:]
'HelpA'
如果你用一些奇怪的index来切割字串,Python直译器也都处理的很好:如果第二个index太大的话就自动代换为字串的长度,如果第二个index比第一个index还要小的话就自动传回 一个空字串。
>>> word[1:100]
'elpA'
>>> word[10:]
''
>>> word[2:1]
''
字串的index甚至可以是负数,若是负数的话,就必须从字串的尾巴开始算起。如下例:
>>> word[-1] # The last character
'A'
>>> word[-2] # The last-but-one character
'p'
>>> word[-2:] # The last two characters
'pA'
>>> word[:-2] # All but the last two characters
'Hel'
但是 -0 事实上是等于 0 ,所以不会从尾巴开始算起。
>>> word[-0] # (since -0 equals 0)
'H'
如果负数index超过字串的范围的话,就自动只会到最大可能的范围,但是如果不是切割一部份的话就会造成错误的情形:
>>> word[-100:]
'HelpA'
>>> word[-10] # error
Traceback (innermost last):
File "<stdin>", line 1
IndexError: string index out of range
最好避免错误的方法是把index看成是指向字元及字元间位置的指标,字串的最开头是0,字串的结尾处就是字串的长度。如下图所示:
+---+---+---+---+---+
| H | e | l | p | A |
+---+---+---+---+---+
0 1 2 3 4 5
-5 -4 -3 -2 -1
上图的数字部分第一行代表的是正数的index,由0到字串的长度,第二行代表的是负数的index。字串的切片(slice)很容易就可以看出来,就是两个index之间的所有字元组合成的字串啰。
对于正数的index来说,如果两个index都在范围之内,字串的切片(slice)的长度就正好是其两个index相减的结果。举例来说
word[1:3]
的长度就正好是 2。
Python内建的 len() 函式可以帮助我们得到字串的长度值。
>>> s = 'supercalifragilisticexpialidocious'
>>> len(s)
34
从Python 2.0 开始Python支援一种新的储存文字资料的资料型态:Unicode物件(object)。使用这个物件你可以储存并控制Unicode的资料(详见 http://www.unicode.org ) ,并且这个物件跟已经存在的字串(string)物件是完全可以互相整合,并且在需要时可以互相转换的。
使用Unicode的好处是可以处理各种不同国家语言的字元。在Unicode之前,在一个code page里只有256个字元可以使用在script中。这个限制的结果常常造成软体国际化(internationalizetion,通常写作 "i18n" -- "i" + 18个字元 + "n")时候的困扰。Unicode的出现定义一个所有script都可以用的code page,如此就解决了这个问题。
在Python中要创造一个Unicode字串就跟创造一个普通字串一样容易:
>>> u'Hello World !'
u'Hello World !'
在引号之前小写的 "u" 代表这个字串是一个Unicode字串。如果你要用到特殊字元,你可能要使用Python的Unicode特殊字元编码( Unicode-Escape encoding)。底下的范例示范如何使用之:
>>> u'Hello\\u0020World !'
u'Hello World !'
上面的
表示在这个位置要插入一个由十六位元0x0020所代表的Unicode字元 (就是空白字元啦)。
u0020
其他的字元也是一样的会被解读为其对应的Unicode字元。由于Unicode对应中的前256 个Unicode字元正好就是大部分欧美国家使用的Latin-1 编码字元,所以其转换是更加的容易。
对于专家们来说,有一个字串的原始模式(raw mode)可以使用。你必须再加上一个小写 'r' 来使Python 使用这一个原始的Unicode特殊字元编码(
Raw-Unicode-Escape
encoding)。只有当
之中的小写 'r' 有奇数的'\'时才会用到这一个编码的。
uXXXX
>>> ur'Hello\u0020World !'
u'Hello World !'
>>> ur'Hello\\u0020World !'
u'Hello\\\\u0020World !'
这个原始模式(raw mode)通常用在当你的字串里面有一大堆的反斜线 '\' 时 ,例如regular expressions(正规表示)时就常用到。
除了这些标准的编码之外, Python还提供了一整套的方法让你可以从以知的编码中创造出Unicode字串来。
Python内建的 unicode() p() 函式可以让你使用所有的已注册的Unicode解码/编码系统(codecs (COders and DECoders))。 这个 codes 可以与大部分的系统互相转换,包括 Latin-1, ASCII , UTF-8 以及 UTF-16 等等。上面所提到的最后两种系统是可变长度的编码系统,可以来储存8位元及16位元的Unicode字元。Python预设使用UTF-8为预设编码系统。当你印出Unicode或是将Unicode写入档案时都会使用到。
>>> u"äöü"
u'\344\366\374'
>>> str(u"äöü")
'\303\244\303\266\303\274'
如果你要使用一个特别的编码系统,但是要印出对应的Unicode码时,你可以使用 unicode() 函式,加上这个编码系统的名称当作第二个参数。
>>> unicode('\303\244\303\266\303\274','UTF-8')
u'\344\366\374'
如果要把Unicode字串转换为一般的字串编码时,可以使用Unicode物件的 encode() 方法(method)。
>>> u"äöü".encode('UTF-8')
'\303\244\303\266\303\274'
(译:硬要翻译list实在太不方便,我直接用原文啰)
Python能够了解一些较为 复杂 的资料型态,这些资料型态大多是用来处理一群的其他资料值。最方便使用的要算是 list 了,一个list可以写成一串由逗号分开的值(东西),然后用角括号括起来便成。放在list里的东西不需要是同一个资料型态
>>> a = ['spam', 'eggs', 100, 1234]
>>> a
['spam', 'eggs', 100, 1234]
跟字串的index用法相同,list的index也由0开始,同样你可以用index来切割lists、组合两个list等等:
>>> a[0]
'spam'
>>> a[3]
1234
>>> a[-2]
100
>>> a[1:-1]
['eggs', 100]
>>> a[:2] + ['bacon', 2*2]
['spam', 'eggs', 'bacon', 4]
>>> 3*a[:3] + ['Boe!']
['spam', 'eggs', 100, 'spam', 'eggs', 100, 'spam', 'eggs', 100, 'Boe!']
与字串不相同的是,字串的个别字元是不可变动的( immutable ),但是list的个别成员是可以自由改变的。
>>> a
['spam', 'eggs', 100, 1234]
>>> a[2] = a[2] + 23
>>> a
['spam', 'eggs', 123, 1234]
你也可以设定一个值或是一个list给一个list的切割部分(slice),但是这样的结果会改变整个list的长度:
>>> # Replace some items:
... a[0:2] = [1, 12]
>>> a
[1, 12, 123, 1234]
>>> # Remove some:
... a[0:2] = []
>>> a
[123, 1234]
>>> # Insert some:
... a[1:1] = ['bletch', 'xyzzy']
>>> a
[123, 'bletch', 'xyzzy', 1234]
>>> a[:0] = a # Insert (a copy of) itself at the beginning
>>> a
[123, 'bletch', 'xyzzy', 1234, 123, 'bletch', 'xyzzy', 1234]
内建的 len() 函式仍然可用在list上面:
>>> len(a)
8
一个list也可以是另一个list的成员(这叫作巢状list, nested list),参考下例:
>>> q = [2, 3]
>>> p = [1, q, 4]
>>> len(p)
3
>>> p[1]
[2, 3]
>>> p[1][0]
2
>>> p[1].append('xtra') # See section 5.1
>>> p
[1, [2, 3, 'xtra'], 4]
>>> q
[2, 3, 'xtra']
注意前一个例子, p[1]
以及 q
事实上指得是同一个物件。我们在之后还会再讨论物件的语法( object semantics
)。
当然Python能做比二加二更有用更复杂的事,例如说,我们可以写一个程式来印出费氏数列( the Fibonacci series )来:
>>> # Fibonacci series:
... # the sum of two elements defines the next
... a, b = 0, 1
>>> while b < 10:
... print b
... a, b = b, a+b
...
1
1
2
3
5
8
这个范例告诉了我们很多新的事情:
a
以及
b
同时都设定了新的值0 与 1。 程式的最后一行再次使用这个技巧,这次在设定符号(等号)的右边我们使用了expression,所有在右边的expression会先求得其值(evaluate)然后才进行设定(assign)的动作。对于在右边的expression来说,其evaluate的次序则是由左至右的。
b < 10
), 这个while 回圈就会一直执行。与C相同的是,对Python而言只要是非零的整数都代表在决定true/false的情况下都代表true,0则代表false。我们也可以在回圈的条件的地方放入字串或是一个list,只要这个字串或list的长度不是零就代表true,若是空字串或空的list就代表false。在这个例子里,我们比较两个值的大小。比较的运算元与C是完全相同的:
<
(小于), >
(大于), ==
(等于),
<=
(小于或等于), >=
(大于或等于) 以及 !=
(不等于)。
>>> i = 256*256
>>> print 'The value of i is', i
The value of i is 65536
如果不想每次的输出都换行的话可以在 print 叙述之后加上逗号,如下所示:
>>> a, b = 0, 1
>>> while b < 1000:
... print b,
... a, b = b, a+b
...
1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987
值得注意的是如果最后一行还没有完成的话,直译器会在印出prompt之前印出新的一行。