基本数据类型
除法/总是得到浮点数
1 | 8 / 5 # 1.6 |
除法//去掉小数部分
1 | 8 // 5 # 1 |
幂次运算使用**
1 | 5 ** 2 # 25 |
字符串使用单引号或者双引号标注,反斜杠\用于转义。如果不希望前置 \ 的字符转义成特殊字符,可以使用 原始字符串,在引号前添加 r 即可
1 | "doesn't" |
字符串字面值可以实现跨行连续输入。实现方式是用三引号:”””…””” 或 ‘’’…’’’,字符串行尾会自动加上回车换行,如果不需要回车换行,在行尾添加 \ 即可。
1 | print("""\ |
字符串可以用 + 合并(粘到一起),也可以用 * 重复
1 | 3 * 'un' + 'ium' |
相邻的两个或多个 字符串字面值 (引号标注的字符)会自动合并
1 | 'Py' 'thon' |
字符串支持 索引 (下标访问),第一个字符的索引是 0。单字符没有专用的类型,就是长度为一的字符串
1 | word = 'Python' |
索引还支持负数,用负数索引时,从右边开始计数
1 | word = 'Python' |
除了索引,字符串还支持 切片。索引可以提取单个字符,切片则提取子字符串。输出结果包含切片开始,但不包含切片结束。因此,s[:i] + s[i:] 总是等于 s
1 | word = 'Python' |
流程控制
Python 的 for 语句不迭代算术递增数值,或是给予用户定义迭代步骤和暂停条件的能力,而是迭代列表或字符串等任意序列,元素的迭代顺序与在序列中出现的顺序一致。
1 | words = ['cat', 'window', 'defenestrate'] |
内置函数 range() 常用于遍历数字序列,该函数可以生成算术级数,生成的序列不包含给定的终止数值;range(10) 生成 10 个值,这是一个长度为 10 的序列,其中的元素索引都是合法的。range 可以不从 0 开始,还可以按指定幅度递增(递增幅度称为 ‘步进’,支持负数)
1 | list(range(5, 10)) # [5, 6, 7, 8, 9] |
range() 返回对象的操作和列表很像,但其实这两种对象不是一回事。迭代时,该对象基于所需序列返回连续项,并没有生成真正的列表,从而节省了空间。这种对象称为可迭代对象 iterable,函数或程序结构可通过该对象获取连续项,直到所有元素全部迭代完毕。for 语句就是这样的架构,sum() 是一种把可迭代对象作为参数的函数
1 | sum(range(4)) # 6 |
pass 语句不执行任何操作。语法上需要一个语句,但程序不实际执行任何动作时,可以使用该语句
1 | while True: |
函数
定义函数使用关键字 def,后跟函数名与括号内的形参列表。函数语句从下一行开始,并且必须缩进。函数内的第一条语句是字符串时,该字符串就是文档字符串。
函数在执行时使用函数局部变量符号表,所有函数变量赋值都存在局部符号表中;引用变量时,首先,在局部符号表里查找变量,然后,是外层函数局部符号表,再是全局符号表,最后是内置名称符号表。因此,尽管可以引用全局变量和外层函数的变量,但最好不要在函数内直接赋值(除非是 global 语句定义的全局变量,或 nonlocal 语句定义的外层函数变量)。
在调用函数时会将实际参数(实参)引入到被调用函数的局部符号表中;因此,实参是使用按值调用来传递的(其中的值始终是对象的引用而不是对象的值)。
函数定义在当前符号表中把函数名与函数对象关联在一起。解释器把函数名指向的对象作为用户自定义函数。还可以使用其他名称指向同一个函数对象,并访问该函数。
1 | def fib(n): # write Fibonacci series up to n |
复杂数据类型
列表
1 | fruits = ['orange', 'apple', 'pear', 'banana', 'kiwi', 'apple', 'banana'] |
insert、remove、sort 等方法只修改列表,返回的默认值为 None 。这是所有Python可变数据结构的设计原则。不是所有数据都可以排序或比较,整数不能与字符串对比,而 None 不能与其他类型对比。
实现堆栈
1 | stack = [3, 4, 5] |
列表也可以用作队列,最先加入的元素,最先取出(“先进先出”);然而,列表作为队列的效率很低。因为,在列表末尾添加和删除元素非常快,但在列表开头插入或移除元素却很慢(因为所有其他元素都必须移动一位)。实现队列最好用 collections.deque,可以快速从两端添加或删除元素。
1 | from collections import deque |
列表可嵌套
1 | matrix = [ |
元祖
元组由多个用逗号隔开的值组成
1 | t = 1, 2, 3 |
元组与列表很像,但使用场景不同,用途也不同。元组是 immutable (不可变的),一般可包含异质元素序列,通过解包或索引访问。列表是 mutable (可变的),列表元素一般为同质类型,可迭代访问。
构造 0 个或 1 个元素的元组比较特殊。
1 | empty = () |
集合
集合是由不重复元素组成的无序容器。基本用法包括成员检测、消除重复元素。集合对象支持合集、交集、差集、对称差分等数学运算。创建集合用花括号或 set() 函数。注意,创建空集合只能用 set(),不能用 {} , {} 创建的是空字典。
1 | basket = {'apple', 'orange', 'apple', 'pear', 'orange', 'banana'} |
字典
字典以 关键字 为索引,关键字通常是字符串或数字,也可以是其他任意不可变类型。只包含字符串、数字、元组的元组,也可以用作关键字。但如果元组直接或间接地包含了可变对象,就不能用作关键字。列表不能当关键字,因为列表可以用索引、切片、append() 、extend() 等方法修改。
可以把字典理解为 键值对 的集合,但字典的键必须是唯一的。花括号 {} 用于创建空字典。另一种初始化字典的方式是,在花括号里输入逗号分隔的键值对,这也是字典的输出方式。
字典的主要用途是通过关键字存储、提取值。用 del 可以删除键值对。用已存在的关键字存储值,与该关键字关联的旧值会被取代。通过不存在的键提取值,则会报错。
对字典执行 list(d) 操作,返回该字典中所有键的列表,按插入次序排列(如需排序,请使用 sorted(d))。检查字典里是否存在某个键,使用关键字 in。
1 | tel = {'jack': 4098, 'sape': 4139} |
del语句
del 语句按索引,而不是值从列表中移除元素。与返回值的 pop() 方法不同, del 语句也可以从列表中移除切片,或清空整个列表(之前是将空列表赋值给切片)。
1 | a = [-1, 1, 66.25, 333, 333, 1234.5] |
用 del 可以删除 dict 里的键值对
1 | tel = {'jack': 4098, 'sape': 4139} |
循环遍历数据结构
在字典中循环时,用 items() 方法可同时取出键和对应的值:
1 | knights = {'gallahad': 'the pure', 'robin': 'the brave'} |
在序列中循环时,用 enumerate() 函数可以同时取出位置索引和对应的值:
1 | for i, v in enumerate(['tic', 'tac', 'toe']): |
逆向循环序列时,先正向定位序列,然后调用 reversed() 函数:
1 | for i in reversed(range(1, 10, 2)): |
按指定顺序循环序列,可以用 sorted() 函数,在不改动原序列的基础上,返回一个重新的序列:
1 | basket = ['apple', 'orange', 'apple', 'pear', 'orange', 'banana'] |
编码风格
- 缩进使用4个空格
- 类和函数的命名要一致;按惯例,命名类用 UpperCamelCase,命名函数与方法用 lowercase_with_underscores。命名方法中第一个参数总是用 self。
模块
模块包含可执行语句及函数定义。这些语句用于初始化模块,且仅在 import 语句 第一次 遇到模块名时执行。模块有自己的私有符号表,用作模块中所有函数的全局符号表。因此,在模块内使用全局变量时,不用担心与用户定义的全局变量发生冲突。为了保证运行效率,每次解释器会话只导入一次模块。如果更改了模块内容,必须重启解释器;仅交互测试一个模块时,也可以使用 importlib.reload()
1 | import importlib |
模块搜索路径
导入 spam 模块时,解释器首先查找名为 spam 的内置模块。如果没找到,解释器再从 sys.path 变量中的目录列表里查找 spam.py 文件。sys.path 初始化时包含以下位置:
- 输入脚本的目录(或未指定文件时的当前目录)。
- PYTHONPATH (目录列表,与 shell 变量 PATH 的语法一样)。
- The installation-dependent default (by convention including a site-packages directory, handled by the site module).
dir()函数
内置函数 dir() 用于查找模块定义的名称。返回结果是经过排序的字符串列表,没有参数时,dir() 列出当前定义的名称。该函数列出所有类型的名称:变量、模块、函数等。dir() 不会列出内置函数和变量的名称。这些内容的定义在标准模块 builtins 里。
1 | dir() |
包
Python 只把含 __init__.py
文件的目录当成包。这样可以防止以 string 等通用名称命名的目录,无意中屏蔽出现在后方模块搜索路径中的有效模块。 最简情况下,__init__.py
只是一个空文件,但该文件也可以执行包的初始化代码,或设置__all__
变量。
1 | __all__ = ["echo", "surround", "reverse"] |
from sound.effects import * 将导入 sound 包中的这三个命名子模块。
从包中导入单个模块,引用时必须使用子模块的全名。
1 | import sound.effects.echo |
另一种导入子模块的方法,不加包前缀也可以使用。
1 | from sound.effects import echo |
Import 语句的另一种变体是直接导入所需的函数或变量
1 | from sound.effects.echo import echofilter |
注意,使用 from package import item 时,item 可以是包的子模块(或子包),也可以是包中定义的函数、类或变量等其他名称。import 语句首先测试包中是否定义了 item;如果未在包中定义,则假定 item 是模块,并尝试加载。如果找不到 item,则触发 ImportError 异常。相反,使用 import item.subitem.subsubitem 句法时,除最后一项外,每个 item 都必须是包;最后一项可以是模块或包,但不能是上一项中定义的类、函数或变量。