标题3.对于python的一个非正式导言 编译之三
在以下实例中,输入input和输出output指令十分有名,出现提示符(>>>和…)prompt的时候,或者没有这样的提示符的时候,你分别要做的事情有所不同:当出现这个提示符的时候,你得重复这个实例,你就必须重新打印提示符后的所有东西。而如果终端中的行列没有提示符,则那只是来自编译器的输出。注意,一行之中自己在实例中给出的次要提示符,那意味着你必须打印一个空行,这被用来终止一个多行指令。
这个手册中的许多实例,甚至还有进入到交互提示符中的实例,也包括了评注,为了理解代码而给出的comment。python中的评注,全都用井字形的符号#起头,延展到那个物理行的末端。一个评注也许出现在行的起头处,也可能出现在一行之中的空白空间或者代码之后,但评注不会出现在一个字符串的文字中间。因为评注是用来说明代码的,它们不会被python的解释器解释。当在实例中打印的时候,这些评论有可能被省略。以下是一个评论实例:
在这里插入代码片>>> #this is the first comment
>>> spam = 0 @ this is the second comment
File "<stdin>", line 1
spam = 0 @ this is the second comment
^
SyntaxError: invalid syntax
>>> # this is the first comment
>>> spam = 1 # this is the second comment
>>> text = "# this is not a comment, because it is inside queto."
>>>
标题3.1 把python作为计算器使用
让我们以几个python评注作为例子试试。启动解释器,等待那个基本提示符>>>出现(不会花很长时间)。
标题3.1.1.数字
这个解释器可以看作为一个简单的计算器:你可以在其中打印出一个表达式,敲回车,就会出现计算结果。表达式的语法是直接的:运算符号+,-,*和/(左斜杠表示除法),这和大多数语言例如巴斯卡Pascal或者C语言是一样的,圆括号()可以用来表示一组数据。如下图:
在这里插入代码片>>> 2+2
4
>>> 3+5*5
28
>>> (50-3*8)/4
6.5
>>> 9/5
1.8
>>>
整数(例如2,4,6,8)有类型int,表示整数类型。带有小数点的那些数(例如5.0,1.6)有类型float,表示浮点数。在本导引手册,其后还会看到有关数字的更多内容。
除法(/)的结果总是浮点数。为了做到地板除floor division ,得到一个整数结果(也就是丢掉一个数的小数部分),可以使用双左斜杠 //运算符,你也可以使用指令%%来计算留下的这个部分。
如下图:
在这里插入代码片>>> 17//3
5
>>> 17/3
5.666666666666667
>>> 17%3
2
>>> 5*3+2
17
>>>
在python中,使用双星号运算子计算幂数也是可能的(注释1):
在这里插入代码片2
>>> 5*3+2
17
>>> 5**3
125
>>> 2**7
128
>>>
等号(=)用来指派一个值给一个变元,指派之后使用下述交互模式提示符,就会展示计算结果,如下图:
在这里插入代码片>>> width =20
>>> height =50
>>> width*height
1000
>>>
如果一个变元没被定义(也就是没有指派值),那么,你试图去使用这个变元,就会送给你一个错误,如下图:
在这里插入代码片PS C:\Users\lenovo> py
Python 3.8.3 (tags/v3.8.3:6f8c832, May 13 2020, 22:37:02) [MSC v.1924 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> 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
>>> tax*price
12.5625
>>> price_
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'price_' is not defined
>>> price+_
113.0625
>>> round(_.2)
File "<stdin>", line 1
round(_.2)
^
SyntaxError: invalid syntax
>>> round(_,2)
113.06
>>>
这个变元应该处理为仅被使用者读取。不明确指派给变元的值——你会创建一个独立的局部变元,该变元使用内置变元同样的名称,并用魔术方式运作。
除了整数 int和浮点float,python也支持其它类型的数字,例如小数Decimal和分数Fraction。Python还有内置函数用来支持复数complex numbers复数,使用符号j或者J后缀去指示那些虚数部分(例如 3+5j)。
标题3.1.2.字符串string
除了数字,python也可以操弄字符串,字符串是可以用各种方式来表达的。它们可以封闭在单引号(’…’)之中或者双引号(’…’)之中,这在指令上没有什么区别(注释2)。可以用右斜杠\去掉引号的指令功能,保留引号自身的功能:如下图
在这里插入代码片>>> 'spam eggs'
'spam eggs'
>>> 'doesn\'t'
"doesn't"
>>> '"yes," they said"
File "<stdin>", line 1
'"yes," they said"
^
SyntaxError: EOL while scanning string literal
>>> '"yes,"they said.'
'"yes,"they said.'
>>> "\"yes"\",they said."
File "<stdin>", line 1
"\"yes"\",they said."
^
SyntaxError: unexpected character after line continuation character
>>> "\"yes"\",they said."
File "<stdin>", line 1
"\"yes"\",they said."
^
SyntaxError: unexpected character after line continuation character
>>> "\"yes\",they said."
'"yes",they said.'
>>> '"isnt\"t",they said.'
'"isnt"t",they said.'
>>>
在交互式解释器中,输出的字符串在引号中封闭,但有一些特殊的字符则用反斜杠标识以逃离这种封闭。有时,这会和输入指令产生一些差异(这种封闭引号可以变化),这两类字符串是等价的。如果该字符串含有一个单引号,没有双引号,用双引号封闭的字符串就是封闭的,否则它就是用单引号封闭。打印函数print(),通过省略封闭引号产生多个读取输出,并且通过逃离和一些特殊字符打印。看下图:
在这里插入代码片SyntaxError: invalid syntax
>>> ‘“isn\'t",they said.'
File "<stdin>", line 1
‘“isn\'t",they said.'
^
SyntaxError: invalid character in identifier
>>> '"Isn\", they said'
'"Isn", they said'
>>> print('"Isn\'t",they said.')
"Isn't",they said.
>>> s =" first line.\n the second line."
>>> s
' first line.\n the second line.'
>>> print(s)
first line.
the second line.
>>>
如果你不想被解释的字符,同时又置于\ 之前的字符作为特殊字符,你可以在第一个引号之前增加一个字母r来使用原初的字符,如下图:
在这里插入代码片>>> print("C:some\name")
C:some
ame
>>> print(r"C:some\name")
C:some\name
>>>
字符串的字码可以跨越多行。一个方法是使用三引号,或者是三双 “”"…""",或者是三单’’’…’’’。这些行的行末自动地包括在字符串中,但也有可能通过加上一个斜杠号\在行的末端来防止这种自动。如下例:
在这里插入代码片>>> print("""\
... usage: thingy [OPTION]
... -h Display this usage message
... -H Hostname to connect to
... )
产生以下输出(注意新起行不包括),注意这里的输入不小心打错,好像很难退出来,笔者还没有找到退出的指令。只有故意弄一个错退出来,或者丢掉编译器的信息,关闭编译器,重新启动。
在这里插入代码片Usage: thingy [OPTIONS]
-h Display this usage message
-H Hostname ro connect to
字符串可以用加号运算符号+连接起来,表示字符串的相加。也可以用乘号*连接起来表示字符串的重复。
在这里插入代码片>>> # 3 times 'un', followed by 'ium'
>>> 3 * 'un' + 'ium'
'unununium'
两个或者以上的字符串,它们先后相继(但每一个都用引号封闭),它们可以自动地加上。
在这里插入代码片>>> 'py' 'thon' 'good'
'pythongood'
当你想要把隔断长字符串合并的时候,这个指令特别有用
在这里插入代码片>>> text = (‘Put several strings within parentheses’
… ‘to have them joined together.’)
text
‘Put several strings within parenthesesto have them joined together.’
这仅在使用用两种字符时起作用,而不用变元或者表达式。
在这里插入代码片>>> prefix = 'py'
>>> prefix 'thon'
File "<stdin>", line 1
prefix 'thon'
^
SyntaxError: invalid syntax
>>> ('un' * 3) 'ium'
File "<stdin>", line 1
('un' * 3) 'ium'
^
SyntaxError: invalid syntax
(这一段没明白意思,接着往下看,大概py是两个特别的字符,它可以直接就作为一个指令,也可以和其它的字符连接起来,用prefix表示)
如果你想连接变元或者一个变元一个字符,那就使用加号+指令:
在这里插入代码片>>> prefix + ‘thon’
‘python’
``>>> prefix + ‘thon’
‘python’
prefix + ‘systax’
‘pysystax’prefix + ‘module’
‘pymodule’
字符串可以编制索引(用下标),常常是第一个字符索引值为0。
在这里插入代码片>>> word = ‘python’
word[0]
‘p’word[4]
‘o’
索引index也可以用负数标记,起点数从右开始:
在这里插入代码片>>> word[-1] # the last character
'n'
>>> word[-2]
'o'
>>> word[-6]
'p'
注意:因为-0和0是等同的,负数的索引起点为-1.。
除了索引,切片slicing也是被支持的。当索引用来包含个体字符时,切片允许你去获得子字符串。
在这里插入代码片>>> word[0:2]
'py'
>>> word[2:5]
'tho'
>>>
注意:起点总是被包括在内,而终端总是排除在外。
这就可以确信 s[:i] + s[i:]总是可以等于s:
在这里插入代码片
```>>> word[:2] +word[2:]
'python'
>>> word[:4] + word[4:]
'python'
切片有很有用的缺省,一个省略掉的第一个索引缺省是0。省略掉的第二个缺省是被切掉的字符
在这里插入代码片
`>>> word[:2]
‘py’
word[4:]
‘on’word[-2:]
‘on’
记住如何切片的一个方法是把索引看作为字符之间的点位,第一个字符位置为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的切片构成了在分别标有i和j的边缘之间的所有字符。
对于非否定的索引,一个切片的长度是索引间的差,如果两边都是没有边界的。例如,索引 word[1:3]长度是2。
试图使用一个太长的索引将会造成错误。
在这里插入代码片
`>>> word[50]
Traceback (most recent call last):
File “”, line 1, in
IndexError: string index out of range``
然而,当运用切片的时候,超出范围的索引切片被优雅地处理。
在这里插入代码片
word[4:50]
‘on’word[50:
…```
Python字符串不能更改,它们是不可改变的。因此,在字符串中去指派某个字符一个索引位置,这会产生错误。例如:
在这里插入代码片
word[50:
… word[0] = ‘J’
File “”, line 2
word[0] = ‘J’
^
SyntaxError: invalid syntaxword[2:] = ‘py’
Traceback (most recent call last):
File “”, line 1, in
TypeError: ‘str’ object does not support item assignment
如果你需要一个不同的字符串,你就应该创建一个新的。
`>>> ‘J’ + word[1:]
‘Jython’
word[:2] + ‘good’
‘pygood’
打印内置函数len()回车,可以给出一个字符串的长度。
`>>> a = ‘supercallfragillsticecpialidocious!’
len(a)
35``
也参看:
文本序列类型——字符串Text Sequence Type — str
字符串是序列类型sequence types的例子,并且支持由这些类型支持的普通操作。
字符串方法String Methods
字符串支持在基本转换和搜寻中的大多数方法
格式化字符串文字Formatted string literals
有内嵌表达式的字符串文字
格式化字符串句法Format String Syntax
有关使用str.format()字符串格式化的信息
打印f风格的字符串格式化printf-style String Formatting
老式格式化操作呼唤,当字符串是%指令的左操作时,该运算子更多的细节就在这里得到描述。
标题3.1.3.列表lists
Python知道许多复合的数据类型,用来把其它的值组合起来。最有才艺的就是列表list,它可以写为一个用逗号(,)来隔开处于方括号([ ])之间的词项列表。列表也许含有不同类型的词项,但通常是那些具有同样类型的词项。见下表:
在这里插入代码片
squares = [1, 4, 9, 16, 25]
squares
[1, 4, 9, 16, 25]```
如同字符串(和所有其它内置序列类型)一样,列表可以索引index和切片slice:
在这里插入代码片
squares[0]
1squares[-1]
25squares[-3:]
[9, 16, 25]```
所有的切片操作返回一个新列表,该列表含有所要求的元素。这意味着以下的切片操作返回了一个列表的浅拷贝swallow copy:
列表也支持像互相关联事物的那些操作,例如+:
在这里插入代码片
squares =[1, 4, 9, 16, 25]
squares[:]
[1, 4, 9, 16, 25]squares + [36, 49, 64, 81, 100]
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]```
不像字符串,字符串是不可更改的,列表则是一个可以更改的类型。也就是说,改变列表中的内容是允许的:
在这里插入代码片
``>>> cubes = [1, 8, 27, 65, 125]
4 ** 3
64cubes[3] = 64
cubes
[1, 8, 27, 64, 125]`
你也可以在列表的尾端添加新词项,运用添加指令append()方法(我们在后面会看到更多有关这个方法的东西):
在列表中使用切片也是可能的,我们既可以改变一个列表的规模大小,也可以把列表全部清除:
内置函数len()也可以运用到列表:
在这里插入代码片```
```>>> letters = ['a', 'b','c', 'd', 'e', 'f', 'g']
>>> letters
['a', 'b', 'c', 'd', 'e', 'f', 'g']
>>> letters[2:5] = ['C', 'D','E']
>>> letters
['a', 'b', 'C', 'D', 'E', 'f', 'g']
>>> letters[2:5] = [ ]
>>> letters
['a', 'b', 'f', 'g']
>>> letters[:] = [ ]
>>> letters
[]
>>> len(letters)
0
在列表中再加进列表nest list(也就是在列表中含有其它的列表),例如:
在这里插入代码片>>> a = ['a', 'b', 'c']
>>> n = [1, 2, 3]
>>> x =[a. n]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'list' object has no attribute 'n'
>>> 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'
标题3.2.朝向编程的第一步
当然,我们可以使用python去完成更为复杂的任务,不止是让它去做简单的加法。例如,我们可以写出一个斐波拉契系列中的一个子系列如下:
在这里插入代码片>>> #斐波拉契系列中的一小段,两个元素和定义了下一个元素
>>> a, b = 0, 1
>>> while a < 10:
... print(a)
... a, b = b, a+b
...
0
1
1
2
3
5
8
>>>
这个例子引导出一些新特性。
首行含有一个多重指派:变元a和b同时得到新值0和1。而末行,这个特性再次被用到,证明了右手边的表达式在值指派发生之前,全都被赋值。右手边的表达式按从左到右的次序全都被赋值。
只要条件被满足(这里是a<10),循环指令while就开始运行。在python中,如同在C语言中一样,任意非0的整数值为真,0则是假的。而循环条件还可以是字符串或者列表的值,实际上,任意序列的值都行。非0长度的任意值为真,空序列为假。在实例中使用的测试是一个简单的比较。标准比较运算子的写法和C语言中的写法相同:<表示小于,>表示大于,==表示等价,<=表示小于或者等于,>=表示大于或者等于,最后,!=表示不等于。
循环体是缩进的:缩进indentation是python组合陈述的方式。在交互提示符中,你必须为每个缩进行打出缩进空格出来,或者用tab键或者用space键。在python实践中,你将使用文本编辑器准备更为复杂的输出,所有正规的文本编辑器都有自动缩进的功能。当一个复合的陈述交互式地进入之时,必定有一个空行在后,指示你继续完成(因为语法分析器parser不可能猜测到你在什么时候是最后一行)。注意在一个基本模块之内的每一行一定是同样的缩进要求。
打印函数print()打印出给定的参数值,这个参数值不同于你想写出的那个表达式,即用处理多重参数,浮点数和字符串数的方式写出的表达式(正如我在计算实例中早就说过的)。字符串打印出来是不用引号的,词项之间有空格,所以你可以优雅地格式化,就像这样:
在这里插入代码片>>> i = 256 * 256
>>> print('The value of i is', i)
The value of i is 65536
>>>
关键字参数end,可以用来避免避免输出之后的新行,或者用一个不同的字符串终止这个输出:
在这里插入代码片>>> a, b = 0, 1
>>> while a < 1000:
... print(a, end=',')
... a, b = b, a+b
...
0,1,1,2,3,5,8,13,21,34,55,89,144,233,377,610,987,>>>
脚注:
[1] 因为’‘运算符号比’-'运算符号有更高的优先权,-32就被解释为-(3**2),由此而有结果-9。为了避免这一点,得到9这个结果,你就应该使用(-3)**2。
[2] 不像其它语言,像\n这样的特殊字符既和单引号,也和双引号有同样的意义。这两者之间唯一的差别是:单引号中间你不必去掉“(但是你必须去掉’,反过来也一样)。