前言写 Python 3 的第一课往往是「字符串怎么表示」。单引号、双引号、三引号这三种写法都能创建字符串但它们之间有没有区别、该用哪种初学者常常是凭感觉选的。先说结论在 Python 3 里单引号和双引号创建的字符串没有任何语义差别它们完全等价选哪个纯粹是风格问题——只要内容里带单引号就用双引号包反之亦然。真正有独立用途的是三引号triple quoted string它能跨行、能保留缩进和换行。这里要顺带点出一个 Python 2 的遗留误解。在 Python 2 里引号前加u表示 Unicode 字符串不加则是字节串这是两套不同的类型。到了 Python 3str本身就是 Unicode 字符串u前缀不再有实际意义3.3 起为了兼容又允许写但不改变任何行为。所以「u...能创建 Unicode、...不能」这种说法在 Python 3 是错的。另外 Python 2.7 已于 2020 年 1 月 1 日停止维护本文一律用 Python 3 的写法。第三部分要讲的是「字符串与数字的运算」。这是新手最容易想当然的地方3 4得到的是34而不是73 - 1直接报错。字符串和数字之间不存在自动转换必须显式用int()、float()、str()打通。一、四种字面量写法写法特点适用场景...单引号内容含双引号时更方便...双引号内容含单引号时更方便...三个单引号可跨行多行文本、文档字符串...三个双引号可跨行多行文本、文档字符串# 适用于 Python 3.8a allows embedded double quotesb allows embedded single quotesprint(a) # allows embedded double quotesprint(b) # allows embedded single quotesprint(a a.replace(, )) # True两种引号完全等价Python 不会因为用哪对引号而产生不同的类型或编码。同一个项目里保持一致、或遵循 PEP 8 之外的项目约定即可。原始字符串与转义反斜杠是转义字符escape character的引导符\n是换行、\t是制表符。想让反斜杠保持字面含义写正则、Windows 路径时常需要用r前缀# 适用于 Python 3.8print(a\tb) # a b —— \t 被解释为制表符print(ra\tb) # a\tb —— 原样输出print(len(\n)) # 1print(len(r\n)) # 2r和u不能一起用ur...是 Python 2 的写法Python 3 里会报SyntaxErroru单独用虽然合法但没有效果。二、三引号与隐式拼接三引号字符串会原样保留换行和缩进因此常用来写多行文本或文档字符串docstring# 适用于 Python 3.8text 第一行第二行第三行有缩进print(text)输出里「第二行」前面的缩进、三行之间的换行都会保留。写多行 SQL、HTML 片段、帮助信息时很方便。作为函数/模块第一条语句时它就成了 docstring可用__doc__读取。另外相邻的字符串字面量会自动合并这是编译期行为# 适用于 Python 3.8print(Py thon) # Pythons abc# s def # 这是语法错误隐式拼接只对字面量成立隐式拼接对字面量有效对变量无效。用它可以跨行写长字符串每行末尾加逗号也行但那是元组不是字符串。三、字符串与数字的运算和*是字符串仅有的两个「算术」运算符语义是拼接和重复# 适用于 Python 3.8print(3 4) # 34 —— 拼接不是相加print(ab * 3) # abababprint(3 * ab) # ababab 乘法满足交换字符串可以在右边print(a b * 2) # abb 优先级乘法先算*的另一个操作数必须是整数浮点会报错# 适用于 Python 3.8print(ab * 2) # abab# print(ab * 2.5) # TypeError: cant multiply sequence by non-int# print(a - b) # TypeError: unsupported operand type(s)# print(6 / 2) # TypeError字符串和数字之间没有隐式转换要参与算术必须显式转# 适用于 Python 3.8x input(请输入一个数字) # input 永远返回字符串n int(x) 1 # 必须先转成 intprint(结果是 str(n)) # 拼接回字符串也要显式转换print(f结果是 {n}) # f-string 会自动格式化无需 str()比较运算这里有个陷阱两个数字字符串比较是按字典序不是按数值# 适用于 Python 3.8print(3 10) # True —— 按码点3 1print(3 10) # True —— 数值比较print(3 3) # False —— 类型不同3 10为真是因为先比第一个字符3和13的码点更大。要按数值比就先把两边转成数字。四、把数字变成字符串的三种方式方式写法说明构造器str(n)最直接任何对象都能转f-stringf{n}需要 3.6可内嵌格式说明符格式化方法{:.2f}.format(n)控制小数位、宽度、对齐# 适用于 Python 3.8n 3.14159print(str(n)) # 3.14159print(f{n:.2f}) # 3.14print(f{n:10.2f}) # 3.14 宽度 10右对齐print({:.2f}.format(n)) # 3.14f-string 从Python 3.6开始提供3.6 以下要用str.format()或%格式化%d % n这种 printf 风格至今仍可用但新代码推荐 f-string。五、input 与数字的衔接input()总是返回字符串即使你输入的是42。所以「读一个数字」的标准套路是先input再转# 适用于 Python 3.8raw input(请输入年龄)try:age int(raw)except ValueError:print(f{raw} 不是合法整数)else:print(f明年你 {age 1} 岁)Python 2 里的input()会把你输入的内容当成 Python 代码求值等价于eval(raw_input())这既危险又反直觉Python 3 的input()对应的是 Python 2 的raw_input()永远返回字符串。老代码里那种「输入数字不用转」的行为在 Python 3 已经不存在。常见坑点以为单引号和双引号有区别❌ 认为abc和abc类型/编码不同纠结该用哪个✅ 两者完全等价只在内容含引号时用另一种包起来给 u 前缀赋予 Python 2 的旧含义❌ 以为u文本才能得到 Unicode不加就是字节串✅ Python 3 里str本身就是 Unicodeu前缀无效果字节串要写b...它创建的是bytes拼字符串和数字时忘了转换❌年龄 18→TypeError: can only concatenate str (not int) to str✅年龄 str(18)或 f-stringf年龄{18}以为字符串减号能做数值运算❌10 - 3→TypeError字符串只支持和*✅int(10) - int(3)得到7拿数字字符串按大小比较❌3 10得到True与直觉相反✅ 先int()再比或使用sorted(nums, keyint)乘字符串用浮点❌- * 2.0→TypeError: cant multiply sequence by non-int of type float✅- * int(2.0)或直接写整数三引号字符串吃掉了不该有的缩进❌ 在函数里写多行文本结果每行都带上了函数体缩进✅ 用textwrap.dedent()处理或把三引号内容顶格书写Python 2 的写法照搬❌print hello、ux当必需、raw_input()当输入函数✅print(hello)、直接x、用input()Python 2 已停止维护新代码不要写 2 的语法总结需求写法备注普通字符串x或x两者完全等价多行字符串x保留换行与缩进不转义反斜杠rx\t正则、路径常用拼接a b两边都必须是 str重复s * nn 必须是 int数字转字符串str(n)/ f-stringf-string 需 3.6字符串转数字int(s)/float(s)失败会抛ValueError记住三条单双引号无差别、u前缀在 Python 3 已无意义、字符串与数字之间必须显式转换。把3 10这类字典序比较的陷阱也记在心里处理用户输入时永远先想一步「这是字符串还是数字」就能避开这一带几乎所有的坑。