python - 合理的入门编程语言
编程语言心法参考:http://www.yinwang.org/blog-cn/2017/07/06/master-pl
英语阅读速成:http://www.yinwang.org/blog-cn/2018/11/23/grammar
记住:晦涩难懂的示例代码直接丢GPT
预期值:知道什么东西(功能点)通过查手册或GPT映射到实施上。这考验的是理解力和阅读能力,所以上面两篇速成心法就发挥了它的核心价值(过一两个月回过头再读读以上两篇文章,直到第N次)
最终目的是看看python的功能点:当知道计算机有“CPU,内存时”没人会去扣CPU上面有多少电路,电压为多少,这不是在工作,这是神经病。目的把握在比如,位置参数,关键词参数,Lambda 表达式,函数注解是什么,并能理解一个示例或引入GPT让它给你一个示例并自己判断它对不对即可。不要变成“张三的李四的王二和麻子有什么关系的CTF风格”
一把梭:比如你有百万资产,拿个十万出来请“专家”教学也是一种有效方式。土豪玩法,直接几万买垠的咨询或报班,还干什么应用浪费生命。
文档部分:教程
https://docs.python.org/3/tutorial/index.html
2.1. Invoking the Interpreter 调用python解释器
- 调用python解释器
linux:/usr/local/bin/python3.12
Windows:py
py命令与 py.exe launcher:说白了就是环境变量与命令启动
https://docs.python.org/3/using/windows.html#launcher
https://docs.python.org/3/using/windows.html#setting-envvars
py
py -2
py -3
- 调用python解释器
python -c command [arg] # 类似于 shell 的 -c 选项
python -m module [arg] # 一些 Python 模块也可用作脚本
命令行交互式编辑与GNU Readline library库:Control-P 快捷键迅速检查是否有此功能
https://tiswww.case.edu/php/chet/readline/rltop.html
运行脚本并随后进入交互模式
-i
所有命令行选项均在命令行和环境中描述
https://docs.python.org/3/using/cmdline.html#using-on-general
python [-bBdEhiIOPqRsSuvVWx?] [-c command | -m module-name | script | - ] [args]
2.1.1. 参数传递
解释器脚本名称和随后的附加参数,它们将变成字符串列表,并分配给 sys 模块中的 argv 变量。可通过执行 import sys 来访问此列表。
python - # sys.argv[0]为 -
python -c command [arg] # sys.argv[0]为 -c
python -m # sys.argv[0] 设置为所定位模块的全名
# 在 -c 命令或 -m 模块之后找到的选项不会被 Python 解释器的选项处理使用,而是留在 sys.argv 中以供命令或模块处理。
2.1.2. 交互模式
交互模式更多信息:https://docs.python.org/3/tutorial/appendix.html#tut-interac
2.2. 解释器及其环境
2.2.1. 源代码编码
默认,Python 源文件被视为 UTF-8 编码。标准库仅使用 ASCII 字符作为标识符。
编辑器必须识别文件是 UTF-8,并且必须使用支持文件中所有字符的字体。
声明除默认编码之外的编码:
# -*- coding: encoding -*-
codecs 是 Python 支持的有效编解码器之一
https://docs.python.org/3/library/codecs.html#module-codecs
要声明使用 Windows-1252 编码,源代码文件的第一行应为:
# -*- coding: cp1252 -*-
UNIX “shebang” line 中的编码声明:
#!/usr/bin/env python3 #! 必须再文件前两个字符,行尾 '\n' 和 '\r\n'也有讲究
# -*- coding: cp1252 -*-
3. Python 的非正式介绍
https://docs.python.org/3/tutorial/introduction.html
注释符
# this is the first comment
spam = 1 # and this is the second comment
# ... and now a third!
text = "# This is not a comment because it's inside quotes."
3.1. 使用 Python 作为计算器
3.1.1. Numbers
+, -, * and /, // 取整,% 取余,** 幂,= 赋值,整数操作数转换为浮点数(数据类型大容器转换),j or J复数,variable _ (视为只读变量。不显式地为其赋值 — 创建一个同名的独立局部变量,用其神奇的行为掩盖内置变量)
变量未定义:variable is not “defined”
3.1.2. Text 文本
Python 可以操作文本(以 str 类型表示所谓的“字符串”)以及数字。
单双引号, 转义符 \, print()的输出省略引号,r 原始字符串 print(r'C:\some\name'),多行 ''' """ 与 \ 防止自动换行,字符串 + 运算符连接(粘合)在一起, * 重复显示,多个相邻的字符串文字(即引号中的字符串)会自动连接起来,字符串可以被索引 负数从右开始计数word[0],切片 word[0:2] 第一个索引默认为零 第二个索引默认为被切片的字符串的大小,内置 len() 长度
文件序列类型 str:字符串是序列类型的示例。
https://docs.python.org/3/library/stdtypes.html#textseq
字符串方法 :字符串支持大量基本转换和搜索的方法。
https://docs.python.org/3/library/stdtypes.html#string-methods
格式化字符串:具有嵌入表达式的字符串文字
https://docs.python.org/3/reference/lexical_analysis.html#f-strings
格式化字符串语法:https://docs.python.org/3/library/string.html#formatstrings
printf 样式的字符串格式化:对应 % 运算符
https://docs.python.org/3/library/stdtypes.html#old-string-formatting
3.1.3. Lists 列表
squares = [1, 4, 9, 16, 25]
与字符串(以及所有其他内置序列类型)一样,列表可以被索引和切片;列表还支持连接等操作;可以更改其内容;list.append() 追加;Python 中的简单赋值永远不会复制数据(内存仅是地址与值,不复制数据那就把同一地址给到另一个变量);len();
shallow copy 浅复制 VS deep copy 深复制:所有切片操作都会返回一个包含所请求元素的新的浅复制列表的副本
https://docs.python.org/3/library/copy.html#shallow-vs-deep-copy
3.2. First Steps Towards Programming 编程的第一步
当以交互方式输入复合语句时,必须补一行表示完成,解析器无法猜测何时输入了最后一行
4.更多控制流工具
4.1. if Statements if语句
4.2. for Statements
4.3. The range() Function
range() and len() 组合迭代索引:逐一访问
4.4. break and continue Statements
break 语句跳出最内层的 for 或 while 循环;continue 语句继续执行循环的下一次迭代
4.5. 循环中的 else 子句
4.6. pass Statements
4.7. match Statements
- 只匹配第一个:match 语句接受一个表达式并将其值与以一个或多个 case 块形式给出的连续模式进行比较。只有匹配的第一个模式才会执行,它还可以将值中的组件(序列元素或对象属性)提取到变量中。
_变量
:case _:
兜里,永远不会匹配失败。- 能匹配到类里面的属性:如果您使用类来构造数据,则可以使用类名,后跟类似于构造函数的参数列表,但能够将属性捕获到变量中。
- unpacking assignments
*,_
通配符 - Sequence patterns
- Mapping patterns:
**rest
允许;**_est
不允许 - as 关键词,提取到变量
- 模式可以使用命名常量
更复杂的教学:https://peps.python.org/pep-0636/
4.8. Defining Functions 定义函数
- keyword def
- 优雅编码: Documentation Strings
- 函数执行与局部变量符号表:symbol table
函数中的所有变量赋值操作都是将值存储在局部符号表中;而变量引用首先在局部符号表中查找,然后在包含的函数的局部符号表中查找,再在全局符号表中查找,最后在内置名称的符号表中查找。 - 实参(局部变量符号表);函数调用函数(创建新的局部变量符号表)
- 函数定义将函数名称与当前符号表中的函数对象相关联。
- 无返回值也会返回值:None
4.9. More on Defining Functions 关于定义函数的更多信息
4.9.1. Default Argument Values 默认参数值
- in keyword:是否包含
4.9.2. Keyword Arguments 关键词参数
- kwarg=value 称为 关键词参数 又称 命名参数
关键词参数:https://docs.python.org/3/glossary.html#term-keyword-argument - keyword arguments 与 positional arguments 的位置关系
**name
参数:接收dict 字典,包含所有关键字参数(形式参数相对应的关键字参数除外)
映射类型 - dict:https://docs.python.org/3/library/stdtypes.html#typesmapping*name
参数:接收 tuple 元组,其中包含形式参数列表之外的位置参数。
元组 - tuple:https://docs.python.org/3/tutorial/datastructures.html#tut-tuples
这一段def cheeseshop(kind, *arguments, **keywords):
讲的是,kind只能接收一个位置的参数;*arguments
任意个位置的参数,**keywords
任意个位置的关键字参数
4.9.3. Special parameters 特殊参数
参数类型, / and * 来指定类型:positional-only 仅位置参数, positional-or-keyword 位置或关键词参数, keyword-only 仅关键词参数
def f(pos1, pos2, /, pos_or_kwd, *, kwd1, kwd2):
----------- ---------- ----------
| | |
| Positional or keyword |
| - Keyword only
-- Positional only
4.9.3.1. Positional-or-Keyword Arguments 位置或关键词参数
- 如果函数定义中不存在 / 和 *,则可以通过位置或关键字将参数传递给函数。
4.9.3.2. Positional-Only Parameters 仅位置参数
- 在 / 之前
4.9.3.3. Keyword-Only Arguments 仅关键词参数
*
第一个是它,则后面全部为仅关键词参数
4.9.3.4. Function Examples
位置参数:standard_arg(2)
关键词参数:standard_arg(arg=2)
4.9.3.5. Recap 回顾
名称对用户不可用,请使用 positional-only。对于 API,使用 positional-only 可以防止将来修改参数名称时破坏 API 更改。
当名称有意义并且函数定义通过明确名称更容易理解或者您想要防止用户依赖传递的参数的位置时,请使用 keyword-only。
4.9.4. Arbitrary Argument Lists 任意参数列表
可以使用任意数量的参数调用函数。这些参数将被 wrapped 包装在 Tuples 元组中(参见 Tuples and Sequences 元组和序列)。在可变数量的参数之前,可以出现零个或多个正常参数。
Tuples and Sequences:https://docs.python.org/3/tutorial/datastructures.html#tut-tuples
4.9.5. Unpacking Argument Lists 解包参数列表
wrapped 包装:说白了1,2,3视为三个;区别于(1,2,3)包装到一起。
Unpacking 解包:说白了(1,2,3)在一起;通过解成1,2,3视为三个
- range();
*
操作符解包列表和元组;**
解包字典
4.9.6. Lambda Expressions Lambda 表达式
可以使用 lambda 关键字创建小型匿名函数。此函数返回其两个参数的总和:lambda a, b: a+b。Lambda 函数可用于需要函数对象的任何地方。它们在语法上被限制为单个表达式。从语义上讲,它们只是普通函数定义的语法糖。
Lambda:https://docs.python.org/3/reference/expressions.html#lambda
4.9.7. Documentation Strings 文档字符串
4.9.8. Function Annotations 函数注解
完全可选的元数据信息:函数注释是关于用户定义函数使用的类型的完全可选的元数据信息(有关更多信息,请参阅 PEP 3107 和 PEP 484)。
Function annotations:https://docs.python.org/3/reference/compound_stmts.html#function
https://peps.python.org/pep-3107/
https://peps.python.org/pep-0484/
4.10. Intermezzo: Coding Style 编码风格
目的:让其他人轻松阅读您的代码
风格:https://peps.python.org/pep-0008/
5. Data Structures 数据结构
5.1. More on Lists 关于列表的更多信息
5.1.1. Using Lists as Stacks 使用列表作为堆栈
后进先出
5.1.2. Using Lists as Queues 使用列表作为队列
先进先出
5.1.3. List Comprehensions 列表推导
一种创建列表的简洁方法
5.1.4. Nested List Comprehensions 嵌套列表推导
5.2. The del statement del语句
可以根据索引而不是值从列表中删除项目
5.3. Tuples and Sequences 元组与序列
- 元组:逗号分隔;immutable 不可变;解包,索引(namedtuple 命名元组)
immutable 不可变:https://docs.python.org/3/glossary.html#term-immutable
namedtuple 命名元组:https://docs.python.org/3/library/collections.html#collections.namedtuple
Sequence Types — list, tuple, range:https://docs.python.org/3/library/stdtypes.html#typesseq
- 列表:mutable 可变;类似;迭代访问
mutable:https://docs.python.org/3/glossary.html#term-mutable
5.4. Sets 集合
集合数据类型;可以使用花括号或 set() 函数来创建集合
5.5. Dictionaries 字典
Python 内置的另一种有用数据类型是 Mapping Types — dict 字典;键,不可变;键值对
Mapping Types — dict 字典:https://docs.python.org/3/library/stdtypes.html#typesmapping
5.6. Looping Techniques 循环技术
items()可同时遍历字典键值对
enumerate() 遍历序列
zip()同时循环两个或多个序列
reversed() 要反向循环序列,首先指定正向序列
sorted() 要按排序顺序循环遍历序列
set() 在序列上可消除重复元素。
5.7. More on Conditions 更多条件
:=
运算符:https://docs.python.org/3/faq/design.html#why-can-t-i-use-an-assignment-in-an-expression
5.8. Comparing Sequences and Other Types 比较序列和其他类型
字符串词序用的unicode code数字点对单个字符进行排序。
非预期的报错:https://docs.python.org/3/library/exceptions.html#TypeError
6. Modules 模块
如果退出 Python 解释器并再次进入,您所做的定义(函数和变量)将丢失。因此,如果您想编写一个稍长的程序,最好使用文本编辑器为解释器准备输入,并使用该文件作为输入运行它。这称为创建脚本。随着程序变得越来越长,您可能希望将其拆分为多个文件以便于维护。您可能还想使用在多个程序中编写的方便的函数,而无需将其定义复制到每个程序中。
为了支持这一点,Python 有一种方法可以将定义放在文件中,并在脚本或解释器的交互式实例中使用它们。这样的文件称为模块;模块中的定义可以导入到其他模块或主模块(您可以在顶层和计算器模式下执行的脚本中访问的变量集合)。
模块是包含 Python 定义和语句的文件。文件名是模块名称加上后缀 .py。在模块中,模块的名称(字符串)可用作全局变量 __name__
的值。
fibo.py; import fibo; fibo.__name__; 经常使用可分配本地名称 fib = fibo.fib
6.1. More on Modules 更多关于模块
模块可以包含可执行语句以及函数定义。这些语句用于初始化模块。它们仅在导入语句中第一次遇到模块名称时执行。(如果文件作为脚本执行,它们也会运行。)
每个模块都有自己的私有命名空间,模块中定义的所有函数都将其用作全局命名空间。因此,模块的作者可以在模块中使用全局变量,而不必担心与用户的全局变量发生意外冲突。另一方面,如果您知道自己在做什么,您可以使用与引用其函数相同的符号 modname.itemname 来接触模块的全局变量。
模块可以导入其他模块。将所有导入语句放在模块(或脚本)的开头是惯例,但并非必须。如果将导入的模块名称放在模块的顶层(在任何函数或类之外),则将其添加到模块的全局命名空间中。
导入语句有一种变体,可将模块中的名称直接导入到导入模块的命名空间中:from fibo import fib, fib2
这不会在本地命名空间中引入导入所基于的模块名称(因此在示例中,fibo 未定义)。
还有一种变体可以导入模块定义的所有名称:from fibo import *
这会导入除以下划线 (_
) 开头的名称之外的所有名称。在大多数情况下,Python 程序员不会使用此功能,因为它会将一组未知的名称引入解释器,可能会隐藏您已经定义的一些内容。
请注意,一般来说,从模块或包导入 * 的做法是不受欢迎的,因为它通常会导致代码可读性差。但是,可以使用它来节省交互式会话中的输入。
as后面的名称直接绑定到导入的模块。
from fibo import fib as fibonacci
模块更改与重载:import importlib; importlib.reload(modulename)
6.1.1. Executing modules as scripts 将模块作为脚本执行
可使该文件作为脚本,又可作为导入模块。只有当模块作为“主”文件执行时,解析命令行的代码才会运行:通常用于为模块提供方便的用户界面,或用于测试目的(将模块作为脚本运行会执行测试套件)
尾巴
python fibo.py <arguments>
if __name__ == "__main__":
import sys
fib(int(sys.argv[1]))
如果导入了模块,则代码不会运行:import fibo
6.1.2. The Module Search Path 模块搜索路径
解释器搜索内置模块 sys.builtin_module_names 中;在变量 sys.path 给出的目录列表中搜索;
sys.path 从以下位置初始化:
包含输入脚本的目录(或未指定文件时的当前目录)。
PYTHONPATH(目录名称列表,语法与 shell 变量 PATH 相同)。
安装相关的默认值(按照惯例包括由站点模块处理的站点包目录)。
sys.builtin_module_names:https://docs.python.org/3/library/sys.html#sys.builtin_module_names
sys.path:https://docs.python.org/3/library/sys.html#sys.path
PYTHONPATH:https://docs.python.org/3/using/cmdline.html#envvar-PYTHONPATH
更多详细信息请参阅 sys.path 模块搜索路径的初始化:https://docs.python.org/3/library/sys_path_init.html#sys-path-init
包含符号链接的目录不会添加到模块搜索路径中。
初始化后,Python 程序可以修改 sys.path。包含正在运行的脚本的目录位于搜索路径的开头,位于标准库路径之前。这意味着将加载该目录中的脚本,而不是库目录中同名的模块。除非有意替换,否则这是一个错误。有关更多信息,请参阅标准模块部分。
标准模块:https://docs.python.org/3/tutorial/modules.html#tut-standardmodules
6.1.3. “Compiled” Python files “编译好的” Python 文件
加载快, 不是运行快
为了加快模块的加载速度,Python 将每个模块的编译版本缓存在 __pycache__
目录中,名称为 module.version.pyc,其中版本编码了编译文件的格式;它通常包含 Python 版本号。例如,在 CPython 版本 3.3 中,spam.py 的编译版本将被缓存为 __pycache__/spam.cpython-33.pyc
。此命名约定允许来自不同版本和不同 Python 版本的编译模块共存。
Python 会根据编译版本检查源代码的修改日期,以查看它是否已过期并需要重新编译。这是一个完全自动的过程。此外,编译后的模块与平台无关,因此可以在具有不同架构的系统之间共享相同的库。
Python 在两种情况下不检查缓存。首先,它总是重新编译并且不存储直接从命令行加载的模块的结果。其次,如果没有源模块,它不会检查缓存。为了支持非源(仅编译)分发,编译模块必须位于源目录中,并且不能有源模块。
程序从 .pyc 文件读取时运行速度不会比从 .py 文件读取时运行速度快;.pyc 文件唯一更快的是它们的加载速度。
模块 compileall 可以为目录中的所有模块创建 .pyc 文件。
PEP 3147 中有关于此过程的更多详细信息,包括决策流程图。
https://peps.python.org/pep-3147/
6.2. Standard Modules 标准模块
library of standard modules 标准模块库,简称 Python Library Reference 参考库
解释器中内置了一些模块;这些模块提供对不属于语言核心但仍然内置的操作的访问,要么是为了提高效率,要么是为了提供对操作系统原语(如系统调用)的访问。此类模块的集合是一个配置选项,也取决于底层平台。例如,winreg 模块仅在 Windows 系统上提供。有一个特别的模块值得关注:sys,它内置于每个 Python 解释器中。
winreg: https://docs.python.org/3/library/winreg.html#module-winreg
sys: https://docs.python.org/3/library/sys.html#module-sys
这两个变量仅在解释器处于交互模式时才定义。
变量 sys.path 是一个字符串列表,用于确定解释器对模块的搜索路径。它被初始化为从环境变量 PYTHONPATH 获取的默认路径,如果未设置 PYTHONPATH,则从内置默认值获取。可以使用标准列表操作对其进行修改:
import sys
sys.path.append('/ufs/guido/lib/python')
6.3. The dir() Function dir()函数
内置函数 dir() 用于找出模块定义了哪些名称
dir() 不会列出内置函数和变量的名称。如果您想要这些函数和变量的列表,它们在标准模块内置函数中定义:
import builtins
dir(builtins)
6.4. Packages 包
导入包的不同语法有直接用或全名路径用的区别。
包是一种使用“带点的模块名称”来构造 Python 模块命名空间的方式。例如,模块名称 A.B 表示包 A 中名为 B 的子模块。就像使用模块可以让不同模块的作者不必担心彼此的全局变量名称一样,使用带点的模块名称可以让 NumPy 或 Pillow 等多模块包的作者不必担心彼此的模块名称。
导入包时,Python 会搜索 sys.path 上的目录,查找包的子目录。
__init__.py
文件是使 Python 将包含该文件的目录视为包所必需的(除非使用命名空间包,这是一个相对高级的功能)。这可以防止具有通用名称(例如字符串)的目录无意中隐藏稍后出现在模块搜索路径上的有效模块。在最简单的情况下,__init__.py
可以只是一个空文件,但它也可以执行包的初始化代码或设置 __all__
变量
命名空间包: https://docs.python.org/3/glossary.html#term-namespace-package
请注意,使用 from package import item 时,item 可以是包的子模块(或子包),也可以是包中定义的其他名称,如函数、类或变量。 import 语句首先测试 item 是否在包中定义;如果没有,则假定它是一个模块并尝试加载它。如果找不到它,则会引发 ImportError 异常。
https://docs.python.org/3/library/exceptions.html#ImportError
6.4.1. Importing * From a Package 导入包里的所有
唯一的解决方案是让包作者提供包的明确索引。 import 语句使用以下约定:如果包的 __init__.py 代码定义了一个名为 __all__ 的列表,则当遇到 from package import * 时,它将
被视为应导入的模块名称列表。当发布新版本的包时,包作者有责任保持此列表为最新。如果包作者认为从他们的包中导入 * 没什么用,他们也可能决定不支持它。例如,文件
sound/effects/__init__.py 可能包含以下代码:
__all__ = ["echo", "surround", "reverse"] 将导入这三个命名子模块。 子模块可能会被本地定义的名称覆盖,比如 reverse 没导入成功与本地名称冲突。
如果未定义 __all__
,则不会将包中的所有子模块导入当前命名空间;它仅确保已导入包(可能运行 __init__.py
中的任何初始化代码),然后导入包中定义的任何名称。这包括 __init__.py
定义的任何名称(以及明确加载的子模块)。它还包括先前的 import 语句明确加载的包的任何子模块。
6.4.2. Intra-package References 包内引用
相对导入
from . import echo
from .. import formats
from ..filters import equalizer
相对导入基于当前模块的名称。由于主模块的名称始终为“__main__”,因此打算用作 Python 应用程序主模块的模块必须始终使用绝对导入。
6.4.3. 多个目录中的包
包支持另一个特殊属性 __path__。在执行该文件中的代码之前,它会被初始化为一个列表,其中包含存放包的 __init__.py 的目录的名称。可以修改此变量;修改会影响将来对包中包含的
模块和子包的搜索。
虽然此功能通常不需要,但它可用于扩展包中找到的模块集。
7. Input and Output
7.1. Fancier Output Formatting 更精美的输出格式
表达式语句; print() ; write() ;sys.stdout
格式化字符串文本
https://docs.python.org/3/tutorial/inputoutput.html#tut-f-strings
f'Results of the {year} {event}'
str.format() : https://docs.python.org/3/library/string.html#formatspec
可以使用字符串切片和连接操作自行处理所有字符串
repr() 或 str() 函数将任何值转换为字符串,str() 函数用于返回相当易于人类阅读的值的表示,而 repr() 则用于生成可由解释器读取的表示(如果没有等效语法,则将强制引发 SyntaxError)。
字符串模块包含一个模板类,它提供了另一种将值替换为字符串的方法
7.1.1. Formatted String Literals 格式化字符串文字
字符串前面加上 f 或 F 并将表达式写为 {expression}:print(f'The value of pi is approximately {math.pi:.3f}.')
7.1.2. The String format() Method String format() 方法
https://docs.python.org/3/library/string.html#formatstrings
7.1.3. Manual String Formatting 手动字符串格式化
print(); str.rjust(); str.ljust(); str.center()。切片操作,如x.ljust(n)[:n]
; str.zfill()
7.1.4. Old string formatting 旧字符串格式
% 运算符(取模)也可用于字符串格式化。给定 format % 值(其中 format 是字符串),format 中的 % 转换规范将被替换为零个或多个值元素。此操作通常称为字符串插值。
https://docs.python.org/3/library/stdtypes.html#old-string-formatting
7.2. Reading and Writing Files 读写文件
两个位置参数,一个关键词参数 open(filename, mode, encoding=None)
mode:r,w,a,r+
encoding="utf-8"
https://docs.python.org/3/library/functions.html#open
在文本模式下,读取时默认将平台特定的行尾(Unix 上为 \n,Windows 上为 \r\n)转换为 \n。在文本模式下写入时,默认将 \n 的出现位置转换回平台特定的行尾。这种对文件数据的幕后修改对于文本文件来说没问题,但会损坏 JPEG 或 EXE 文件中的二进制数据。在读取和写入此类文件时,请务必小心使用二进制模式。
处理文件对象时,使用 with 关键字是一种很好的做法。这样做的好处是,即使在某个时候引发异常,文件在其套件完成后也会正确关闭。使用 with 也比编写等效的 try-finally 块短得多
如果您没有使用 with 关键字,那么您应该调用 f.close() 来关闭文件并立即释放其使用的任何系统资源。
调用 f.write() 时不使用 with 关键字或调用 f.close() 可能会导致 f.write() 的参数无法完全写入磁盘,即使程序成功退出。
7.2.1. Methods of File Objects 文件对象的方法
f.read(size) f.read() f.readline() list(f) f.readlines() f.write(string) f.tell() f.seek(offset, whence)
从文件中读取行
for line in f:
print(line, end='')
7.2.2. Saving structured data with json 使用json保存结构化数据
可以轻松地将字符串写入文件或从文件中读取字符串。
流行的数据交换格式:JSON(JavaScript 对象表示法)https://www.json.org/
标准模块称为 json
序列化:Python 数据 --》字符串表示形式
反序列化:字符串表示形式 --》Python 数据
json.dumps() 序列化字符串
json.dump() 序列化为文本文件
JSON 文件必须采用 UTF-8 编码。使用 encoding="utf-8" 打开时 JSON 文件作为 文本文件, 可供读取和写入。
这种简单的序列化技术可以处理列表和字典,但是 在 JSON 中序列化任意类实例需要一些额外的工作。 参考资料为 json 模块包含对此的解释。
pickle 是协议,允许任意复杂的 Python 对象的序列化。特定于 Python,不能用于与应用程序通信 用其他语言写的。默认情况下它也是不安全的: 反序列化来自不受信任来源的pickle数据可以执行
https://docs.python.org/3/library/pickle.html#module-pickle
8. Errors and Exceptions 错误和异常
8.1. Syntax Errors 语法错误
语法错误,也称为解析错误
SyntaxError: invalid syntax
8.2. Exceptions 异常
执行期间检测到的错误被称为异常
大多数异常不被处理 但是,程序会导致错误消息
ZeroDivisionError: division by zero
NameError: name 'spam' is not defined
TypeError: can only concatenate str (not "int") to str
标准异常名称是内置标识符(不是保留关键字)
内置异常列出了内置异常及其含义:https://docs.python.org/3/library/exceptions.html#bltin-exceptions
8.3. Handling Exceptions 处理异常
可以编写程序来处理选定的异常。请看下面的示例,它要求用户输入,直到输入了有效的整数,但允许用户中断程序(使用 Control-C 或操作系统支持的任何方式);请注意,用户生成的中断通过引发 KeyboardInterrupt 异常来表示。
https://docs.python.org/3/library/exceptions.html#KeyboardInterrupt
except ValueError 为捕获到的异常是一个未处理的异常
处理非致命的异常:
BaseException 是所有异常的共同基类。它的一个子类 Exception 是所有非致命异常的基类。通常不处理不是 Exception 子类的异常,因为它们用于指示程序应该终止。它们包括由 sys.exit() 引发的 SystemExit 和当用户希望中断程序时引发的 KeyboardInterrupt。
Exception 可以用作通配符来捕获(几乎)所有异常。但是,最好尽可能具体地说明我们打算处理的异常类型,并允许任何意外异常继续传播。
处理异常的最常见模式是打印或记录异常,然后重新引发它(允许调用者也处理异常)
8.4. Raising Exceptions 引发异常
raise 语句允许程序员强制发生指定的异常。
raise 的唯一参数表示要引发的异常。这必须是异常实例或异常类(从 BaseException 派生的类,例如 Exception 或其子类之一)。如果传递了异常类,它将通过调用不带参数的构造函数来隐式实例化
8.5. Exception Chaining 异常链
如果在 except 部分内发生未处理的异常,则会将正在处理的异常附加到该部分并包含在错误消息中,表明一个异常是另一个异常的直接结果
有关链接机制的更多信息,请参阅内置异常:https://docs.python.org/3/library/exceptions.html#bltin-exceptions
8.6. User-defined Exceptions 用户定义异常
程序可以通过创建新的异常类来命名自己的异常(有关 Python 类的更多信息,请参阅类)。异常通常应直接或间接地从 Exception 类派生。
可以定义异常类来执行任何其他类可以执行的任何操作,但通常保持简单,通常只提供一些属性,允许异常处理程序提取有关错误的信息。
大多数异常的名称以“Error”结尾,类似于标准异常的命名。
许多标准模块定义自己的异常来报告它们定义的函数中可能发生的错误。
8.7. Defining Clean-up Actions 定义清理操作
8.8. Predefined Clean-up Actions 预定义清理操作
8.9. Raising and Handling Multiple Unrelated Exceptions 引发和处理多个不相关的异常
8.10. Enriching Exceptions with Notes 通过注释丰富异常
9. Classes 类
9.1. A Word About Names and Objects 关于名称和对象
9.2. Python Scopes and Namespaces Python 作用域和命名空间
命名空间:从名称到对象的映射。
虽然作用域是静态确定的,但它们是动态使用的。在执行期间的任何时候,都有 3 或 4 个嵌套作用域,其命名空间可直接访问:
最内层的作用域(首先搜索)包含本地名称
任何封闭函数的作用域(从最近的封闭作用域开始搜索)包含非本地名称,但也包含非全局名称
倒数第二个作用域包含当前模块的全局名称
最外层的作用域(最后搜索)是包含内置名称的命名空间
9.2.1. Scopes and Namespaces Example 范围和命名空间示例
nonlocal ,global
9.3. A First Look at Classes 初识类
9.3.1. Class Definition Syntax 类定义语法
class ClassName:
当输入类定义时,会创建一个新的命名空间,并将其用作局部作用域 — 因此,对局部变量的所有赋值都会进入这个新的命名空间。特别是,函数定义会在此处绑定新函数的名称。
当类定义正常退出时(通过 end ),将创建一个类对象。这基本上是类定义创建的命名空间内容的wrapper 包装器;恢复原始局部范围(在输入类定义之前有效的范围),并将类对象绑定到类定义标头中给出的类名(示例中的 ClassName)。
9.3.2. Class Objects 类对象
类对象支持两种操作:属性引用和实例化。
属性引用:obj.name
类实例化:使用函数表示法。只需假设类对象是一个无参数函数,该函数返回该类的新实例即可。x = MyClass()
创建该类的新实例并将该对象分配给局部变量 x
许多类喜欢创建具有自定义为特定初始状态的实例的对象。因此,类可以定义一个名为 __init__()
的特殊方法
当类定义 __init__()
方法时,类实例化会自动为新创建的类实例调用 __init__()
。
__init__()
方法可以有参数,以实现更大的灵活性。
9.3.3. Instance Objects 实例对象
实例对象唯一能理解的操作是属性引用。有两种有效的属性名称:数据属性和方法。
实例对象的有效方法名称取决于其类。根据定义,类的所有作为函数对象的属性都定义了其实例的相应方法。
9.3.4. Method Objects 方法对象
方法的特殊之处在于实例对象作为函数的第一个参数传递。
9.3.5. Class and Instance Variables 类和实例变量
实例变量用于每个实例独有的数据
类变量用于类的所有实例共享的属性和方法
9.4. Random Remarks 随笔
每个值都是一个对象,因此有一个类(也称为其类型)。它存储为 object.__class__
。
9.5. Inheritance 继承
Inheritance 继承 derived class 派生类
class DerivedClassName(BaseClassName):
class DerivedClassName(modname.BaseClassName):
构造类对象时,会记住基类。这用于解析属性引用:如果在类中找不到请求的属性,则继续在基类中搜索。如果基类本身是从其他类派生的,则此规则将递归应用。
9.5.1. Multiple Inheritance 多重继承
class DerivedClassName(Base1, Base2, Base3):
如果在 DerivedClassName 中找不到某个属性,则在 Base1 中搜索它,然后(递归地)在 Base1 的基类中搜索它,如果在那里找不到它,则在 Base2 中搜索它,依此类推。
事实上,它比这稍微复杂一些;方法解析顺序会动态变化以支持对 super() 的协作调用。有关更多详细信息,请参阅 Python 2.3 方法解析顺序。
https://docs.python.org/3/howto/mro.html#python-2-3-mro
9.6. Private Variables 私有变量
Python 中不存在“私有”实例变量,即除了从对象内部访问之外无法访问的变量。但是,大多数 Python 代码都遵循一个惯例:带有下划线前缀的名称(例如 _spam
)应被视为 API 的非公共部分(无论是函数、方法还是数据成员)。它应被视为实现细节,如有更改,恕不另行通知。
有关详细信息和特殊情况,请参阅私有名称修改规范。https://docs.python.org/3/reference/expressions.html#private-name-mangling
9.7. Odds and Ends 碎碎念
@dataclass 注解:https://docs.python.org/3/library/dataclasses.html#module-dataclasses
9.8. Iterators 迭代器
9.9. Generators 生成器
生成器是一种简单而强大的迭代器创建工具
9.10. Generator Expressions 生成器表达式
10. Brief Tour of the Standard Library 标准库简介
os 模块
import os
:os.open()
不要用from os import *
,小心覆盖内置的open()函数
对于日常的文件和目录管理任务,shutil 模块提供了更易于使用的更高级别的接口
10.2. File Wildcards 文件通配符
glob 模块提供了通过目录通配符搜索制作文件列表的功能
10.3. Command Line Arguments 命令行参数
常用实用程序脚本经常需要处理命令行参数。这些参数以列表形式存储在 sys 模块的 argv 属性中。
argparse 模块提供了更复杂的机制来处理命令行参数。
10.4. Error Output Redirection and Program Termination 错误输出重定向和程序终止
sys 模块还具有 stdin、stdout 和 stderr 的属性。后者可用于发出警告和错误消息,即使 stdout 已重定向。
终止脚本最直接的方法是使用 sys.exit()。
10.5. String Pattern Matching 字符串模式匹配
re 模块提供了用于高级字符串处理的正则表达式工具。对于复杂的匹配和操作,正则表达式提供了简洁、优化的解决方案
当只需要简单功能时,string methods 字符串方法是首选,因为它们更易于阅读和调试
10.6. Mathematics 数学
math 模块可以访问用于浮点数学的底层 C 库函数
random 模块提供进行随机选择的工具
statistics 模块计算数值数据的基本统计属性(平均值、中位数、方差等)
SciPy 项目 https://scipy.org 有许多其他用于数值计算的模块。
10.7. Internet Access 互联网接入
有许多模块用于访问互联网和处理互联网协议。其中最简单的两个是用于从 URL 检索数据的 urllib.request 和用于发送邮件的 smtplib
10.8. Dates and Times 日期和时间
datetime 模块提供用于以简单和复杂方式处理日期和时间的类。虽然支持日期和时间算法,但实现的重点是高效提取成员以进行输出格式化和处理。该模块还支持时区感知的对象。
10.9. Data Compression 数据压缩
模块直接支持常见的数据归档和压缩格式,包括:zlib、gzip、bz2、lzma、zipfile 和 tarfile。
10.10. Performance Measurement 性能测量
timeit 模块
与 timeit 的细粒度相比,profile 和 pstats 模块提供了用于识别较大代码块中时间关键部分的工具。
10.11. Quality Control 质量控制
开发高质量软件的一种方法是,在开发每个函数时为其编写测试,并在开发过程中频繁运行这些测试。
doctest 模块提供了一种工具,用于扫描模块并验证嵌入在程序文档字符串中的测试。
unittest 模块不像 doctest 模块那么轻松,但是它允许在单独的文件中维护更全面的测试集
10.12. Batteries Included 内置电池
Python 秉承“内置电池”的理念。这一点从其大型软件包的复杂和强大功能中可见一斑。例如:
xmlrpc.client 和 xmlrpc.server 模块使实现远程过程调用成为一项几乎微不足道的任务。尽管模块名称如此,但无需直接了解或处理 XML。
email 包是一个用于管理电子邮件消息的库,包括 MIME 和其他基于 RFC 2822 的消息文档。与实际发送和接收消息的 smtplib 和 poplib 不同,email 包具有一套完整的工具集,用于构建或解码复杂的消息结构(包括附件)以及实现互联网编码和标头协议。
json 包为解析这种流行的数据交换格式提供了强大的支持。 csv 模块支持直接读取和写入逗号分隔值格式的文件,数据库和电子表格通常支持这种格式。 xml.etree.ElementTree、xml.dom 和 xml.sax 包支持 XML 处理。这些模块和包一起大大简化了 Python 应用程序和其他工具之间的数据交换。
sqlite3 模块是 SQLite 数据库库的包装器,提供可以使用略微非标准的 SQL 语法进行更新和访问的持久数据库。
许多模块都支持国际化,包括 gettext、locale 和 codecs 包。
11. Brief Tour of the Standard Library — Part II 标准库简介(第二部分)
11.1. Output Formatting 输出格式
reprlib 模块提供了 repr() 的定制版本,用于缩写显示大型或深度嵌套的容器
pprint 模块提供了更复杂的控制,可以以解释器可读的方式打印内置和用户定义的对象。当结果超过一行时,“漂亮的打印机”会添加换行符和缩进,以更清楚地显示数据结构
textwrap 模块可以格式化文本段落以适应给定的屏幕宽度
locale 模块访问特定文化数据格式的数据库。locale 的 format 函数的 grouping 属性提供了一种使用组分隔符格式化数字的直接方法
11.2. Templating 模板
string 模块包含一个多功能的 Template 类,其简化的语法适合最终用户编辑。这允许用户自定义其应用程序,而无需更改应用程序。
11.3. Working with Binary Data Record Layouts 使用二进制数据记录布局
struct 模块提供 pack() 和 unpack() 函数来处理可变长度的二进制记录格式。以下示例显示了如何在不使用 zipfile 模块的情况下循环遍历 ZIP 文件中的标头信息。打包代码“H”和“I”分别代表两字节和四字节无符号数字。“<”表示它们是标准大小且采用小端字节顺序
11.4. Multi-threading 多线程
线程是一种将不连续依赖的任务解耦的技术。线程可用于提高接受用户输入的应用程序的响应能力,而其他任务则在后台运行。一个相关的用例是在另一个线程中并行运行 I/O 和计算。
高级 threading 线程模块:主程序继续运行的同时在后台运行任务
多线程应用程序的主要挑战是协调共享数据或其他资源的线程。为此,线程模块提供了许多同步原语,包括锁、事件、条件变量和信号量。
虽然这些工具功能强大,但微小的设计错误可能会导致难以重现的问题。因此,任务协调的首选方法是将对资源的所有访问集中在单个线程中,然后使用 queue 队列模块将来自其他线程的请求提供给该线程。使用队列对象进行线程间通信和协调的应用程序更易于设计、更易读且更可靠。
11.5. Logging
logging 日志模块提供了功能齐全且灵活的日志系统。最简单的方法是将日志消息发送到文件或 sys.stderr
11.6. Weak References 弱引用
Python 会自动进行内存管理(对大多数对象进行引用计数,并通过垃圾回收消除循环)。内存在最后一个引用被消除后不久就会被释放。
这种方法适用于大多数应用程序,但有时需要仅在对象被其他程序使用时才跟踪它们。不幸的是,仅仅跟踪它们会创建一个使它们永久存在的引用。weakref 模块提供了用于跟踪对象的工具,而无需创建引用。当不再需要对象时,它将自动从弱引用表中删除,并触发弱引用对象的回调。典型的应用包括缓存创建成本高昂的对象
11.7. Tools for Working with Lists 列表操作工具
内置列表类型可以满足许多数据结构需求。但是,有时需要具有不同性能权衡的替代实现。
array 模块提供了一个数组对象,它类似于一个列表,只存储同类数据,并且存储得更紧凑。以下示例显示了一个数字数组,该数组存储为两个字节的无符号二进制数(类型代码“H”),而不是常规 Python int 对象列表的每个条目通常 16 个字节
collections 模块提供了一个双端队列对象,它类似于一个列表,但从左侧添加和弹出的速度更快,但在中间查找的速度较慢。这些对象非常适合实现队列和广度优先树搜索
除了备选列表实现之外,该库还提供其他工具,例如具有用于操作排序列表的函数的 bisect 模块
heapq 模块提供基于常规列表实现堆的函数。最低值条目始终保持在零位置。这对于重复访问最小元素但不想运行完整列表排序的应用程序很有用
11.8. Decimal Floating-Point Arithmetic 十进制浮点运算
decimal 模块为十进制浮点运算提供了 Decimal 数据类型。
12. Virtual Environments and Packages 虚拟环境和包
12.1. Introduction
Python 应用程序通常会使用不属于标准库的包和模块。应用程序有时需要特定版本的库,因为应用程序可能需要修复特定错误,或者应用程序可能使用过时的库接口版本编写。
这意味着一个 Python 安装可能无法满足每个应用程序的要求。如果应用程序 A 需要某个模块的 1.0 版本,但应用程序 B 需要 2.0 版本,则这两个要求存在冲突,安装 1.0 或 2.0 版本都将导致一个应用程序无法运行。
解决此问题的方法是创建一个虚拟环境,即一个包含特定 Python 版本的 Python 安装以及许多附加包的独立目录树。
然后,不同的应用程序可以使用不同的虚拟环境。为了解决前面冲突要求的示例,应用程序 A 可以拥有自己的虚拟环境,其中安装了 1.0 版本,而应用程序 B 拥有另一个虚拟环境,其中安装了 2.0 版本。如果应用程序 B 需要将库升级到 3.0 版本,这不会影响应用程序 A 的环境。
12.2. Creating Virtual Environments 创建虚拟环境
用于创建和管理虚拟环境的模块称为 venv。venv 将安装运行命令的 Python 版本(由 --version 选项报告)。例如,使用 python3.12 执行命令将安装版本 3.12。
要创建虚拟环境,请确定要放置它的目录,然后使用以下目录路径以脚本形式运行 venv 模块:
python -m venv tutorial-env
如果不存在 tutorial-env 目录,这将创建它,并在其中创建包含 Python 解释器副本和各种支持文件的目录。
虚拟环境的常见目录位置是 .venv。此名称使目录通常隐藏在您的 shell 中,从而不妨碍您,同时为其指定一个名称来解释目录存在的原因。它还可以防止与某些工具支持的 .env 环境变量定义文件发生冲突。
创建虚拟环境后,您可以激活它。
在 Windows 上,运行:tutorial-env\Scripts\activate
在 Unix 或 MacOS 上,运行:source tutorial-env/bin/activate
(此脚本是为 bash shell 编写的。如果您使用 csh 或 fish shell,则可以使用替代的 activate.csh 和 activate.fish 脚本。)
激活虚拟环境将更改 shell 的提示符以显示您正在使用的虚拟环境,并修改环境,以便运行 python 可以获得特定版本的 Python 和安装。
要停用虚拟环境,请键入
deactivate
12.3. Managing Packages with pip 使用 pip 管理软件包
默认情况下,pip 将从 Python 软件包索引中安装软件包。您可以在 Web 浏览器中访问 Python 软件包索引来浏览它。
https://pypi.org/
pip 有许多子命令:“install”、“uninstall”、“freeze”等等。(有关 pip 的完整文档,请参阅安装 Python 模块指南。)
https://docs.python.org/3/installing/index.html#installing-index
python -m pip install novas
python -m pip install requests==2.6.0
python -m pip install --upgrade 将软件包升级到最新版本
python -m pip uninstall 后跟一个或多个包名将从虚拟环境中删除包。
python -m pip show 将显示有关特定包的信息
python -m pip list 将显示虚拟环境中安装的所有软件包
python -m pip freeze > requirements.txt 将生成类似的已安装软件包列表
python -m pip install -r requirements.txt
当您编写了一个包并希望将其发布在 Python 包索引中时,请参阅 Python 打包用户指南。
https://packaging.python.org/en/latest/tutorials/packaging-projects/
13. What Now? 现在怎么办?
本教程是 Python 文档集的一部分。该文档集中的其他一些文档包括:https://docs.python.org/3/library/index.html#library-index
它提供了有关类型、函数和标准库中的模块的完整(但简洁)参考资料。标准 Python 发行版包含大量附加代码。有用于读取 Unix 邮箱、通过 HTTP 检索文档、生成随机数、解析命令行选项、压缩数据和许多其他任务的模块。
安装 Python 模块解释了如何安装其他 Python 用户编写的附加模块。https://docs.python.org/3/installing/index.html#installing-index
Python 语言参考:对 Python 语法和语义的详细解释。这本书读起来很费劲,但作为该语言本身的完整指南还是很有用的。
https://docs.python.org/3/reference/index.html#reference-index
更多 Python 资源:
https://www.python.org:主要的 Python 网站。它包含代码、文档和指向网络上与 Python 相关的页面的指针。
https://docs.python.org:快速访问 Python 的文档。
https://pypi.org:Python 软件包索引,以前也被称为 Cheese Shop,是可供下载的用户创建的 Python 模块的索引。一旦开始发布代码,您就可以在此处注册,以便其他人可以找到它。
https://code.activestate.com/recipes/langs/python/:Python Cookbook 是一个相当大的代码示例、较大模块和有用脚本的集合。特别值得注意的贡献被收集在一本名为 Python Cookbook 的书中(O'Reilly & Associates,ISBN 0-596-00797-3。)
https://pyvideo.org 收集了来自会议和用户组会议的与 Python 相关的视频链接。
https://scipy.org:科学 Python 项目包括用于快速数组计算和操作的模块,以及用于线性代数、傅里叶变换、非线性求解器、随机数分布、统计分析等的一系列软件包。
对于与 Python 相关的问题和问题报告,您可以发布到新闻组 comp.lang.python,或将其发送到邮件列表 python-list@python.org。新闻组和邮件列表是网关,因此发布到其中一个的消息将自动转发到另一个。每天都有数百条帖子,提出(和回答)问题、建议新功能和宣布新模块。邮件列表存档可在 https://mail.python.org/pipermail/ 上找到。
在发布之前,请务必查看常见问题解答列表(也称为 FAQ)。常见问题解答回答了许多反复出现的问题,并且可能已经包含您的问题的解决方案。
https://docs.python.org/3/index.html
- Interactive Input Editing and History Substitution 交互式输入编辑和历史替换
14.1. Tab Completion and History Editing Tab 补全和历史记录编辑
14.2. Alternatives to the Interactive Interpreter 交互式解释器的替代方案 - Floating-Point Arithmetic: Issues and Limitations 浮点运算:问题和限制
15.1. Representation Error 表述错误 - Appendix 附录
16.1. Interactive Mode 交互模式
16.1.1. Error Handling 错误处理
16.1.2. Executable Python Scripts 可执行 Python 脚本
16.1.3. The Interactive Startup File 交互式启动文件
16.1.4. The Customization Modules 定制模块