3. Python 快速上手:先把它用起来
对应官方文档:3. An Informal Introduction to Python 一句话导读:不铺垫、不讲大道理,直接把数字、文本、列表和循环挨个敲一遍,让你第一次体会到「Python 怎么这么顺手」。
这一章官方叫「非正式介绍」,意思是不追求严谨定义,先让你用起来。例子原本写在交互模式里,村长统一改成能直接复制运行的 .py 写法,用 # -> 注释标出关键输出;涉及 >>> 的地方保留 text 块给你对照。
3.1 把 Python 当计算器
打开解释器看到 >>> 就能开始算。+ - * / 和数学里差不多,括号照常用来分组。官方特别提醒一句:除法 / 永远返回浮点数,哪怕能整除也一样。
print(2 + 2) # -> 4
print(50 - 5 * 6) # -> 20
print((50 - 5 * 6) / 4) # -> 5.0
print(8 / 5) # -> 1.6
3.1.1 数字
整数(int)是 2、20 这种不带小数点的,带小数点的 5.0、1.6 是浮点数(float);两者混算时整数会自动提升成浮点,结果自然是浮点。
| 运算符 | 含义 | 例子 | 结果 |
|---|---|---|---|
/ | 普通除法,总返回浮点 | 17 / 3 | 5.666... |
// | 向下取整除 | 17 // 3 | 5 |
% | 取余 | 17 % 3 | 2 |
** | 乘方 | 2 ** 7 | 128 |
print(17 / 3) # -> 5.666666666666667
print(17 // 3, 17 % 3) # -> 5 2
print(-17 // 3) # -> -6
print(5 ** 2, 2 ** 7) # -> 25 128
print(-3 ** 2, (-3) ** 2) # -> -9 9
width, height = 20, 5 * 9
print(width * height) # -> 900
print(4 * 3.75 - 1) # -> 14.0
z = 3 + 5j
print(z, z.real, z.imag) # -> (3+5j) 3.0 5.0
print(z.conjugate()) # -> (3-5j)
print(1j * 1j) # -> (-1+0j)
你可以这样理解 // 和 %:商 * 除数 + 余数 == 被除数。两个隐藏坑也在上面:// 是向下取整(-17 // 3 得 -6),以及 ** 优先级高于左边的负号(-3 ** 2 是 -9)。= 赋值本身不显示结果,混合 width, height = ... 这种写法叫多重赋值,3.2 还会细讲。复数用 j 或 J 后缀表示虚部,不是数学课本里的 i,z.real / z.imag / z.conjugate() 分别取实部、虚部和共轭。
在交互模式里,最后打印出来的值会自动塞进一个叫 _ 的变量,方便接着算;官方叮嘱把它当只读,别自己给 _ 赋值。
>>> tax = 12.5 / 100
>>> price = 100.50
>>> price * tax
12.5625
>>> price + _
113.0625
>>> round(_, 2)
113.06
_ 是交互模式专属便利,写进 .py 文件请老实给变量起名:
tax, price = 12.5 / 100, 100.50
last = price * tax
print(last, price + last, round(price + last, 2)) # -> 12.5625 113.0625 113.06
除了 int、float,标准库还有 Decimal、Fraction,上面那几行也一并演示了复数。
村长划重点:
/永远返回float;//是向下取整,不是「砍掉小数」。负数场景最容易在这里翻车,记住-17 // 3 == -6。
3.1.2 文本
字符串(str)用单引号或双引号包起来都行,效果一样;引号里想再放引号,要么换另一种引号,要么用 \ 转义。交互模式直接敲变量名会把引号和转义一起显示,想看「人话版」用 print(),repr() 则把转义原样摊给你看。加 r 前缀得到原始字符串,反斜杠不再被当转义,写 Windows 路径 r'C:\some\name' 特别香(但原始字符串不能以奇数个反斜杠结尾)。三引号 """...""" 能跨多行,换行原样进串,开头的 \ 可以吃掉第一行换行。
print('spam eggs') # -> spam eggs
print("doesn't") # -> doesn't
print('doesn\'t') # -> doesn't
print('"Yes," they said.') # -> "Yes," they said.
s = 'First line.\nSecond line.'
print(repr(s)) # -> 'First line.\nSecond line.'
print('a\tb') # -> a[TAB]b
print(r'a\tb') # -> a\tb
usage = """\
Usage: thingy
-h Help
"""
print(repr(usage)) # -> 'Usage: thingy\n -h Help\n'
print(3 * 'un' + 'ium') # -> unununium
print('Py' 'thon') # -> Python
prefix = 'Py'
print(prefix + 'thon') # -> Python
word = 'Python'
print(word[0], word[5], word[-1]) # -> P n n
print(word[0:2], word[2:5]) # -> Py tho
print(word[:2], word[4:], word[-2:]) # -> Py on on
print(word[4:42], repr(word[42:])) # -> on ''
print(len(word)) # -> 6
try:
word[0] = 'J'
except TypeError as exc:
print(type(exc).__name__) # -> TypeError
print('J' + word[1:]) # -> Jython
字符串能用 + 拼接、* 重复;挨着写的两个字面量会自动合并,但这个特性只认字面量,变量和表达式得老实用 +。索引从 0 开始,负数从右往左数(-1 是最后一个);切片 [起:止] 含头不含尾,省掉的起点默认 0、终点默认长度,所以 word[:i] + word[i:] 永远等于原串。单个索引越界抛 IndexError,切片越界却被悄悄截断(word[42:] 只是空串)。最后那条最关键:字符串不可变,给下标赋值一定报 TypeError,想改只能拼个新串;len() 返回长度。
村长划重点:切片含头不含尾、越界不报错;字符串不可变,
s[0] = 'J'必报错。这两条几乎承包了新手一半的字符串 bug。
3.1.3 列表
列表用方括号装逗号分隔的元素,是最常用的复合类型。和字符串一样能索引、切片、用 + 拼接,而且切片一律返回新列表;区别是列表可变:能改下标、能 append()、还能给切片赋值一次替换一段甚至清空。
squares = [1, 4, 9, 16, 25]
print(squares[0], squares[-1], squares[-3:]) # -> 1 25 [9, 16, 25]
print(squares + [36, 49]) # -> [1, 4, 9, 16, 25, 36, 49]
cubes = [1, 8, 27, 65, 125]
cubes[3] = 64
cubes.append(216)
cubes.append(7 ** 3)
print(cubes) # -> [1, 8, 27, 64, 125, 216, 343]
letters = ['a', 'b', 'c', 'd', 'e', 'f', 'g']
letters[2:5] = ['C', 'D', 'E']
print(letters) # -> ['a', 'b', 'C', 'D', 'E', 'f', 'g']
letters[2:5] = []
print(letters) # -> ['a', 'b', 'f', 'g']
letters[:] = []
print(letters, len(letters)) # -> [] 0
a, n = ['a', 'b', 'c'], [1, 2, 3]
x = [a, n]
print(x[0], x[0][1], len(x)) # -> ['a', 'b', 'c'] b 2
rgb = ["Red", "Green", "Blue"]
rgba = rgb
rgba.append("Alph")
print(rgb is rgba, rgb) # -> True ['Red', 'Green', 'Blue', 'Alph']
copy = rgb[:]
copy[-1] = "Alpha"
print(copy[-1], rgb[-1]) # -> Alpha Alph
len() 同样适用于列表,列表里还能再套列表,取元素就一层层往下写下标。还有个官方专门点名的心智模型:简单赋值从不复制数据,rgba = rgb 只是给同一个列表又贴了个标签,从哪个标签改另一个都看得见;想要真副本得用切片 [:]。
村长划重点:字符串不可变、列表可变;而且
b = a不复制列表,只复制引用。想改副本又不碰原列表,记得写b = a[:]。
3.2 编程第一步
终于要写「像程序」的东西了。官方用斐波那契开场:前两项是 0 和 1,之后每项等于前两项之和。
a, b = 0, 1
while a < 10:
print(a)
a, b = b, a + b
i = 256 * 256
print('The value of i is', i)
a, b = 0, 1
while a < 1000:
print(a, end=',')
a, b = b, a + b
print()
print(bool(0), bool(5), bool(''), bool('hi'), bool([]), bool([1]))
0
1
1
2
3
5
8
The value of i is 65536
0,1,1,2,3,5,8,13,21,34,55,89,144,233,377,610,987,
False True False True False True
这一小段一口气塞了四个新东西。多重赋值:a, b = 0, 1 让两个变量同时拿到新值;循环体里 a, b = b, a + b 是精华——右边 b 和 a + b 会先全部算完再一起赋给左边,所以不需要临时变量存旧的 a,拆成两行普通赋值反而会算错。while 循环:条件为真就一直转;官方顺带说明真假规则,数字非零为真、0 为假,字符串和列表这类序列长度非零为真、空为假,比较运算符是 <、>、==、<=、>=、!=。缩进:循环体靠缩进分组,这是 Python 的语法不是排版习惯,同一块每行必须缩进一致,乱了直接 IndentationError,交互模式写完复合语句还要补一个空行,别混用 Tab 和空格。print() 与 end:它把多个参数用空格连起来、字符串不带引号地打印,默认结尾自动换行,写成 end=',' 就改成逗号,写成 end='' 连分隔符都不要。
村长划重点:缩进是语法不是审美;
end=''能关掉.py文件统一用 4 个空格,别让编辑器的 Tab 偷偷混进来。
本章小结
/总返回浮点,//向下取整,%取余,**乘方;复数用j后缀,交互模式有只读的_变量。- 字符串支持转义、原始字符串
r、三引号、+拼接、*重复、索引切片,但不可变。 - 列表同样能索引切片,却可变:可改下标、
append()、切片赋值;b = a只是共享引用,副本要写a[:]。 - 切片含头不含尾、越界不报错;
len()对字符串和列表都管用。 - 斐波那契示例带出多重赋值(右侧先全部求值)、
while、缩进分组,以及print(..., end=...)。