3. Python 语言简介
在接下来的栗子中,输入和输出通过提示符的有和无来加以区分(>>> 和 …): 重复一下这个例子,当提示符出现的时候,你必须在提示符之后输入所有东西。不是以提示符开头的一行行,就是解释器的输出内容。注意,一行中出现次级提示符本身,意味着你必须输入一个空行。这一般用于结束一个多行命令。
这个手册中的许多例子,甚至那些在交互命令提示符中的代码,都包含有注释。Python 中的注释以一个井号开头,#
,注释一直扩展到这一行的结束位置。注释可以出现在一行的开头,也可以跟在在空格或代码后面,但是不能在一个字符串字面量内部。一个在字符串字面量内部的井号仅仅就是一个井号字符而已。因为注释是为了使代码更清晰而不会被Python 解释,所以它们在实例中会被忽略。
一些例子:
# 这是第一个注释
spam = 1 # 这是第二个注释
# ... 现在,这是第三个!
text = "# This is not a comment because it's inside quotes."
3.1 把 Python 当做计算器
让我们尝试一些简单的 Python 命令吧。启动解释器,等待主提示符 >>>(时间不会 很久的)
3.1.1 数字
解释器作为一个简单的计算器:你可以在解释器中输入一个表达式,然后将会输出它的值。表达式的语法很直接:+,-,*,以及 / 的操作可以和其他大多数语言一样工作(比如 Pascal 或者 C)。圆括号(())可以用作表达式块。举个栗子:
>>> 2 + 2
4
>>> 50 - 5*6
20
>>> (50 - 5*6) / 4
5.0
>>> 8 / 5 # 除法总返回一个浮点数(floating point number)
1.6
整数(比如2,4,20) 都具有 int
类型。有小数部分的数字具有 float
类型。我们以后会在这个教程中看到更多关于数字类型的内容。
除法符号 (/) 总会返回一个 float 类型的数字。如果想要做浮点除法,并且得到一个整数的结果 (丢弃所有小数部分),你可以使用 // 操作符。计算余数,可以使用 %:
>>> 17 / 3 # 普通的除法返回浮点数float
5.666666666666667
>>>
>>> 17 // 3 # 取整除法(floor division) 丢弃小数部分
5
>>> 17 % 3 # % 操作符返回除法的余数
2
>>> 5 * 3 + 2 # 商 * 除数 + 余数
17
在 Python 里,可以使用 ** 操作符来计算幂运算
注释: 因为 ** 比 - 的优先级更高,所以 -3**2 会被解释为 -(3**2),也就是结果是 -9。你可以使用 (-3)**2 来避免这种情况。
>>> 5 ** 2 # 5 的平方
25
>>> 2 ** 7 # 2 的 7 次幂
128
等号 (=) 用来给一个变量赋值。在下一条交互指令之前,不会有结果打印出来:
>>> width = 20
>>> height = 5 * 9
>>> width * height
900
如果变量没有“定义”(指定一个值),尝试使用它的时候会报错:
>>> n # 使用一个未定义的变量
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'n' is not defined
对浮点数完全支持。对多种类型进行运算时,整形操作数会被转为浮点数:
>>> 4 * 3.75 - 1
14.0
在交互模式中,最后一个打印出来的表达式的值会被赋给变量_
。这就意味着,你当你把 Python 当做一个桌面计算器来使用时,连续运算会变得比较方便。举个栗子:
>>> tax = 12.5 / 100
>>> price = 100.50
>>> price * tax
12.5625
>>> price + _
113.0625
>>> round(_, 2)
113.06
这个变量 (译者注:指的是下划线变量 _ ) 应该被用户当做一个只读的变量来对待。不要显式的给下划线变量赋值,否则这种神奇的行为会创建出一个独立的,和下划线变量同名的本地变量。
除了 int 和 float 之外, Python 还支持其他的数字类型,比如 十进制数 和 分数。Python 也有对 复数 的内建支持,并且使用 j 或者 J 后缀来表示复数的虚部。
3.1.2 字符串
除了数字之外,Python 也可以操作字符串,可以有若干种表示方式。他们可以包含在一对单引号 (‘…’) 或者双引号 (“…”) 中,而结果相同。\ 可以用来对引号进行转义。
注释:不像其他语言,特定字符如,\n 用单引号 (‘…’) 和双引号 (“…”) 的意思一样。两者唯一的区别是,在单引号中你不必转义双引号 (但是你必须要转义 \‘),反之亦然。
>>> 'spam eggs' # single quotes 单引号
'spam eggs'
>>> 'doesn\'t' # use \' to escape the single quote... 转义
"doesn't"
>>> "doesn't" # ...or use double quotes instead 双引号
"doesn't"
>>> '"Yes," he said.'
'"Yes," he said.'
>>> "\"Yes,\" he said."
'"Yes," he said.'
>>> '"Isn\'t," she said.'
'"Isn\'t," she said.'
在交互式解释器中,输出的字符串被引号包含,而且特定的字符会被反斜线转义。虽然这个看起来有时候会和输入的不要一样 (引号可以改变), 但是它们是相等的。如果字符串包含一个单引号而没有双引号,那么字符串就要被包含在双引号中,否则就包含在单引号中。print() 函数通过忽略掉转义引号的转义符号,会输出一个可读性更好的结果:
>>> '"Isn\'t," she said.'
'"Isn\'t," she said.'
>>> print('"Isn\'t," she said.')
"Isn't," she said.
>>> s = 'First line.\nSecond line.' # \n 表示换行
>>> s # 不用 print(), \n 就会在输出结果中
'First line.\nSecond line.'
>>> print(s) # 用了 print(), \n 会换行
First line.
Second line.
如果你不想让 \ 转义特定字符,你可以通过在第一个引号之前加一个 r 来使用 原始字符串 (raw strings) :
>>> print('C:\some\name') # 这里 \n 代表换行!
C:\some
ame
>>> print(r'C:\some\name') # 注意在引号之前的 r
C:\some\name
字符串字面量可以跨越多行。一种方法就是使用“三引号”:"""..."""
或者 '''...'''
。每一行的结尾会自动包含在字符串中,但是可以通过在每一行的结尾加上一个 \ 来避免这种情况。下面的栗子:
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
字符串可以通过 + 操作符拼接,可以通过 * 操作符进行重复:
>>> # 3 乘以 'un', 加上 'ium'
>>> 3 * 'un' + 'ium'
'unununium'
两个以上相邻的 字符串字面量 (在引号中的字符串) 会自动拼接。
>>> 'Py' 'thon'
'Python'
但是,这种自动拼接只会在两个字面量中起作用,在变量或表达式不会起作用:
>>> prefix = 'Py'
>>> prefix 'thon' # 不能把变量和字符串字面量拼接在一起
...
SyntaxError: invalid syntax
>>> ('un' * 3) 'ium'
...
SyntaxError: invalid syntax
如果你想把变量之间,或者变量和字符串字面量拼接在一起,使用 +
:
>>> prefix + 'thon'
'Python'
当你想把长字符串分开时,这个特性特别有用:
>>> text = ('Put several strings within parentheses '
... 'to have them joined together.')
>>> text
'Put several strings within parentheses to have them joined together.'
字符串可以被索引 (下标), 第一个字符的索引值是 0。不存在单独的字符类型。一个字符就是一个长度为 1 的字符串:
>>> word = 'Python'
>>> word[0] # 第 0 个字符
'P'
>>> word[5] # 第 5 个字符
'n'
索引值也可以是负数,代表从右往左数第几个:
>>> word[-1] # 最后一个字符
'n'
>>> word[-2] # 倒数第二个字符
'o'
>>> word[-6]
'P'
注意,因为 -0 和 0 相同,所以负的索引值从 -1 开始。
除了索引之外,也支持 slice (切分) 字符串。字符串索引用来或许某个字符个体,而 slice 允许你获取 子字符串:
>>> word[0:2] # 从第0个(包括第0个)到第2个(不包括第2个)字符串
'Py'
>>> word[2:5] # 从第2个(包括第2个)到第5个(不包括第5个)字符串
'tho'
注意,开头总是被包含在内,结尾永远不被包含。所以就可以确定 s[:i] + s[i:]
永远等于 s
:
>>> word[:2] + word[2:]
'Python'
>>> word[:4] + word[4:]
'Python'
因为索引值有很有用的默认属性。省略的第一个索引值缺省为 0,省略的第二个索引值就会缺省为被 slice 字符串的长度。
>>> word[:2] # character from the beginning to position 2 (excluded)
'Py'
>>> word[4:] # characters from position 4 (included) to the end
'on'
>>> word[-2:] # characters from the second-last (included) to the end
'on'
一个记住 slice 是如何工作的方法是,想象一个位于字符串之间的索引,这个索引的第一个字符左边缘是 0。然后最后一个字符 n 的右边缘具有索引 n。举个栗子:
+---+---+---+---+---+---+
| P | y | t | h | o | n |
+---+---+---+---+---+---+
0 1 2 3 4 5 6
-6 -5 -4 -3 -2 -1
第一行数字显示了在字符串中从0~6的位置。第二行显示了倒数的位置。从 i 到 j 的 slice 组成了所有位于标签 i 和 j 之间的所有字符。
对于非倒数的索引值来说,如果两个索引值都在字符串的范围之内, slice 的子字符串的长度就是两个索引值之差。例如,word[1:3]
的长度就是2.
尝试使用一个过大的索引值会导致错误的结果:
>>> word[42] # the word only has 6 characters
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError: string index out of range
然而,当进行 slice 操作时,超出范围的 slice 会被优雅的处理:
>>> word[4:42]
'on'
>>> word[42:]
''
Python 字符串不能被改变——他们是不可变的 (immutable)。因此,给一个字符串的某个索引位置赋值会导致错误:
>>> word[0] = 'J'
...
TypeError: 'str' object does not support item assignment
>>> word[2:] = 'py'
...
TypeError: 'str' object does not support item assignment
如果你需要一个不同的字符串,你应该新建一个字符串:
>>> 'J' + word[1:]
'Jython'
>>> word[:2] + 'py'
'Pypy'
内置的函数 len() 返回一个字符串的长度:
>>> s = 'supercalifragilisticexpialidocious'
>>> len(s)
34
补充:
- 文本有序类型—— str。字符串是有序队列类型的实例,并且支持这种类型的操作。
- 字符串方法。字符串支持大量的基本转换和搜索的方法。
- 格式化的字符串字面量。字符串字面量有嵌入的表达式。
- 格式化字符串语法。使用 str.format() 来格式化字符串的信息。
- printf 风格的字串串格式化。当字符串是 % 操作符左边的操作数时,旧式的格式化操作就会被调用。这里有更多细节。
3.1.3 列表 (Lists)
Python 可以识别大量的复合数据结构,一般用来把其他的数值组合在一起。用途最广的就是 列表,它可以写成在一对方括号中由逗号隔开的一个列表。列表可能包含不同类型的数据,但是通常所有的元素 (item) 都是同一个类型的。
>>> squares = [1, 4, 9, 16, 25]
>>> squares
[1, 4, 9, 16, 25]
就像字符串 (以及其他所有内建队列类型) 一样,列表可以被索引和 slice :
>>> squares[0] # 索引一个列表会返回一个元素
1
>>> squares[-1]
25
>>> squares[-3:] # slice 操作返回一个新的列表
[9, 16, 25]
所有的 slice 操作都会返回一个包含所要求的元素的新列表。这就意味着下面的 slice 操作会返回原来列表的一个新的副本 (浅复制):
>>> squares[:]
[1, 4, 9, 16, 25]
列表也支持像拼接这样的操作:
>>> squares + [36, 49, 64, 81, 100]
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
不像字符串是 不可变 的,列表是一种 可变 (mutable)的类型。也就是说,你可以改变这个数组的内容:
>>> cubes = [1, 8, 27, 65, 125] # 这有一些错误
>>> 4 ** 3 # 4的立方是64,不是65!
64
>>> cubes[3] = 64 # 替换掉了错误的数字
>>> cubes
[1, 8, 27, 64, 125]
你也可以通过使用 append() 方法,在列表的末尾加上新的元素。(我们在后面江湖看到更多关于方法的内容)
>>> cubes.append(216) # add the cube of 6
>>> cubes.append(7 ** 3) # and the cube of 7
>>> cubes
[1, 8, 27, 64, 125, 216, 343]
slice 的时候赋值也是可以的,这甚至可以改变列表的长度或者把他完全清空:
>>> letters = ['a', 'b', 'c', 'd', 'e', 'f', 'g']
>>> letters
['a', 'b', 'c', 'd', 'e', 'f', 'g']
>>> # replace some values
>>> letters[2:5] = ['C', 'D', 'E']
>>> letters
['a', 'b', 'C', 'D', 'E', 'f', 'g']
>>> # now remove them
>>> letters[2:5] = []
>>> letters
['a', 'b', 'f', 'g']
>>> # clear the list by replacing all the elements with an empty list
>>> letters[:] = []
>>> letters
[]
内建的函数 len() 也可以用于列表:
>>> letters = ['a', 'b', 'c', 'd']
>>> len(letters)
4
列表还可以嵌套 (在列表中包含其他列表),举个栗子:
>>> a = ['a', 'b', 'c']
>>> n = [1, 2, 3]
>>> x = [a, n]
>>> x
[['a', 'b', 'c'], [1, 2, 3]]
>>> x[0]
['a', 'b', 'c']
>>> x[0][1]
'b'