Python 教程阅读简记

2019/04/08

地址:https://docs.python.org/zh-cn/3/tutorial/index.html

本篇仅仅记录一下,不是阅读笔记,不推荐阅读

1. 课前甜点

2. 使用 Python 解释器

2.1. 调用解释器

1

python

2

python -c command [arg] ...

其中 command 要换成想执行的指令

3

python -m module [arg] ...

这会执行 module 的源文件,就跟你在命令行把路径写全了一样

4

python -i test.py

在运行后进入交互模式

2.1.1. 传入参数

import sys
sys.args

2.1.2. 交互模式

2.2. 解释器的运行环境

2.2.1. 源文件的字符编码

# -*- coding: encoding -*-

or

#!/usr/bin/env python3
# -*- coding: cp1252 -*-

3. Python 的非正式介绍

3.1. Python 作为计算器使用

3.1.1. 数字

3.1.2. 字符串

3.1.3. 列表

3.2. 走向编程的第一步

4. 其他流程控制工具

4.1. if 语句

4.2. for 语句

如果在循环内需要修改序列中的值(比如重复某些选中的元素),推荐你先拷贝一份副本

for w in words[:]:  # Loop over a slice copy of the entire list.
    if len(w) > 6:
        words.insert(0, w)

# words

4.3. range() 函数

range() 所返回的对象在许多方面表现得像一个列表,但实际上却并不是。

我们说这样的对象是 可迭代的

4.4. break 和 continue 语句,以及循环中的 else 子句

循环语句可能带有一个 else 子句;它会在循环遍历完列表 (使用 for) 或是在条件变为假 (使用 while) 的时候被执行,但是不会在循环被 break 语句终止时被执行。 这可以通过以下搜索素数的循环为例来进行说明:

for n in range(2, 10):
    for x in range(2, n):
        if n % x == 0:
            print(n, 'equals', x, '*', n//x)
            break
    else:
        # loop fell through without finding a factor
        print(n, 'is a prime number')

# 2 is a prime number
# 3 is a prime number
# 4 equals 2 * 2
# 5 is a prime number
# 6 equals 2 * 3
# 7 is a prime number
# 8 equals 2 * 4
# 9 equals 3 * 3

(是的,这是正确的代码。仔细看: else 子句属于 for 循环, 不属于 if 语句。)

当和循环一起使用时,else 子句与 try 语句中的 else 子句的共同点多于 if 语句中的子句: try 语句中的 else 子句会在未发生异常 (expect) 时执行,而循环中的 else 子句则会在未发生 break 时执行。 有关 try 语句和异常的更多信息,请参阅 处理异常。

4.5. pass 语句

4.6. 定义函数

即使没有 return 语句的函数也会返回一个值,尽管它是一个相当无聊的值。这个值称为 None。

4.7. 函数定义的更多形式

4.7.1. 参数默认值

4.7.2. 关键字参数

关键字参数必须跟随在位置参数的后面

*args**kwargs

def a(*args, *kwargs):
	# args 是一个列表
	# kwargs 是一个字典

4.7.3. 任意的参数列表

4.7.4. 解包参数列表

* 可以解包列表 ** 可以解包字典

4.7.5. Lambda 表达式

lambda a, b: a+b

4.7.6. 文档字符串

def my_function():
    """Do nothing, but document it.

    No, really, it doesn't do anything.
    """
    pass

print(my_function.__doc__)

4.7.7. 函数标注

def f(ham: str, eggs: str = 'eggs') -> str:
    print("Annotations:", f.__annotations__)
    print("Arguments:", ham, eggs)
    return ham + ' and ' + eggs

f('spam')
# Annotations: {'ham': <class 'str'>, 'return': <class 'str'>, 'eggs': <class 'str'>}
# Arguments: spam eggs
# 'spam and eggs'

4.8. 小插曲:编码风格

5. 数据结构

5.1. 列表的更多特性

list.append(x)

在列表的末尾添加一个元素。相当于 a[len(a):] = [x] 。

list.extend(iterable)

使用可迭代对象中的所有元素来扩展列表。相当于 a[len(a):] = iterable 。

list.insert(i, x)

在给定的位置插入一个元素。第一个参数是要插入的元素的索引,所以 a.insert(0, x) 插入列表头部, a.insert(len(a), x) 等同于 a.append(x) 。

list.remove(x)

移除列表中第一个值为 x 的元素。如果没有这样的元素,则抛出 ValueError 异常。

list.pop([i])

删除列表中给定位置的元素并返回它。如果没有给定位置,a.pop() 将会删除并返回列表中的最后一个元素。( 方法签名中 i 两边的方括号表示这个参数是可选的)。

list.clear()

删除列表中所有的元素。相当于 del a[:] 。

list.index(x[, start[, end]])

返回列表中第一个值为 x 的元素的从零开始的索引。如果没有这样的元素将会抛出 ValueError 异常。

可选参数 start 和 end 是切片符号,用于将搜索限制为列表的特定子序列。返回的索引是相对于整个序列的开始计算的,而不是 start 参数。

list.count(x)

返回元素 x 在列表中出现的次数。

list.sort(key=None, reverse=False)

对列表中的元素进行排序(参数可用于自定义排序,解释请参见 sorted())。

list.reverse()

反转列表中的元素。

list.copy()

返回列表的一个浅拷贝。相当于 a[:] 。

像 insert ,remove 或者 sort 方法,只修改列表,没有打印出返回值——它们返回默认值 None 。这是 Python 中所有可变数据结构的设计原则

5.1.1. 列表作为栈使用

列表方法使得列表作为堆栈非常容易,最后一个插入,最先取出(“后进先出”)

appendpop

5.1.2. 列表作为队列使用

列表也可以用作队列,其中先添加的元素被最先取出 (“先进先出”);然而列表用作这个目的相当低效。因为在列表的末尾添加和弹出元素非常快,但是在列表的开头插入或弹出元素却很慢 (因为所有的其他元素都必须移动一位)。

若要实现一个队列, collections.deque 被设计用于快速地从两端操作。

5.1.3. 列表推导式

squares = list(map(lambda x: x**2, range(10)))

或者,等价于

squares = [x**2 for x in range(10)]

列表推导式的结构是由一对方括号所包含的以下内容:

一个表达式,后面跟一个 for 子句,然后是零个或多个 for 或 if 子句。 其结果将是一个新列表,由对表达式依据后面的 for 和 if 子句的内容进行求值计算而得出。

举例来说,以下列表推导式会将两个列表中不相等的元素组合起来:

[(x, y) for x in [1,2,3] for y in [3,1,4] if x != y]

# [(1, 3), (1, 4), (2, 3), (2, 1), (2, 4), (3, 1), (3, 4)]

5.1.4. 嵌套的列表推导式

5.2. del 语句

a = [-1, 1, 66.25, 333, 333, 1234.5]

del a[0]

a # [1, 66.25, 333, 333, 1234.5]

del a[2:4]

a # [1, 66.25, 1234.5]

del a[:]

a # []

del 也可以被用来删除整个变量

del a

此后再引用 a 时会报错(直到另一个值被赋给它)。我们会在后面了解到 del 的其他用法。

5.3. 元组和序列

他们是 序列 数据类型(参见 序列类型 — list, tuple, range)中的两种。

一个元组由几个被逗号隔开的值组成

元组是 immutable (不可变的),其序列通常包含不同种类的元素,并且通过解包(这一节下面会解释)或者索引来访问(如果是 namedtuples 的话甚至还可以通过属性访问)。

列表是 mutable (可变的),并且列表中的元素一般是同种类型的,并且通过迭代访问。

一个特殊的问题是构造包含 0 个或 1 个元素的元组

() # 空

1, # 以,结尾,1个元素的元组

5.4. 集合

集合是由不重复元素组成的无序的集。它的基本用法包括成员检测和消除重复元素。集合对象也支持像 联合,交集,差集,对称差分等数学运算

花括号或 set() 函数可以用来创建集合。注意:要创建一个空集合你只能用 set() 而不能用 {},因为后者是创建一个空字典。

a = {'a', 'b', 'c'}

a # {'a', 'b', 'c'}

'a' in a # Trues
a = set('abracadabra')
b = set('alacazam')

a # {'a', 'b', 'c', 'd', 'r'}

a - b # {'r', 'd', 'b'}

a | b # {'a', 'c', 'r', 'd', 'b', 'm', 'z', 'l'}

a & b # {'a', 'c'}

a ^ b # {'r', 'd', 'b', 'm', 'z', 'l'}

类似于 列表推导式,集合也支持推导式形式

a = {x for x in 'abracadabra' if x not in 'abc'}
a # {'r', 'd'}

5.5. 字典

字典是以 关键字 为索引的,关键字可以是任意不可变类型,通常是字符串或数字。

list(d) 将返回包含该字典中所有键的列表,按插入次序排列 (如需其他排序,则要使用 sorted(d))。

dict() 构造函数可以直接从键值对序列里创建字典。

dict([('sape', 4139), ('guido', 4127), ('jack', 4098)])

# {'sape': 4139, 'guido': 4127, 'jack': 4098}

当关键字是简单字符串时,有时直接通过关键字参数来指定键值对更方便

dict(sape=4139, guido=4127, jack=4098)

# {'sape': 4139, 'guido': 4127, 'jack': 4098}

5.6. 循环的技巧

5.7. 深入条件控制

5.8. 序列和其它类型的比较

序列对象可以与相同类型的其他对象比较。它们使用 字典顺序 进行比较:

字典顺序对字符串来说,是使用单字符的 Unicode 码的顺序。下面是同类型序列之间比较的例子

(1, 2, 3)              < (1, 2, 4)
[1, 2, 3]              < [1, 2, 4]
'ABC' < 'C' < 'Pascal' < 'Python'
(1, 2, 3, 4)           < (1, 2, 4)
(1, 2)                 < (1, 2, -1)
(1, 2, 3)             == (1.0, 2.0, 3.0)
(1, 2, ('aa', 'ab'))   < (1, 2, ('abc', 'a'), 4)

注意对不同类型对象来说,只要待比较对象提供了合适的比较方法,就可以使用 < 和 > 来比较。例如,混合数值类型是通过他们的数值进行比较的,所以 0 等于 0.0,等等。否则,解释器将抛出一个 TypeError 异常,而不是随便给出一个结果。

6. 模块

6.1. 有关模块的更多信息

6.1.1. 以脚本的方式执行模块

# a/b.py
print(__name__)

# main.py
from a import b
print(__name__)

# a.b
# __main__

6.1.2. 模块搜索路径

6.1.3. “编译过的”Python 文件

6.2. 标准模块

变量 sys.ps1 和 sys.ps2 定义用作主要和辅助提示的字符串:

>>> import sys
>>> sys.ps1
'>>> '
>>> sys.ps2
'... '
>>> sys.ps1 = 'C> '
C> print('Yuck!')
Yuck!
C>

6.3. dir() 函数

6.4. 包

为了让 Python 将目录当做包,目录中必须包含 __init__.py 文件

当然它也可以执行包的初始化代码,或者定义稍后会介绍的 __all__ 变量

6.4.1. 从包中导入 *

如果一个包的 __init__.py 代码定义了一个名为 __all__ 的列表,它会被视为在遇到 from package import * 时应该导入的模块名列表

6.4.2. 子包参考

6.4.3. 多个目录中的包

7. 输入输出

7.1. 更漂亮的输出格式

7.1.1. 格式化字符串文字

7.1.2. 字符串的 format() 方法

7.1.3. 手动格式化字符串

7.1.4. 旧的字符串格式化方法

'%s' % 'a'

可在 printf-style String Formatting 部分找到更多信息。

7.2. 读写文件

7.2.1. 文件对象的方法

7.2.2. 使用 json 保存结构化数据

8. 错误和异常

8.1. 语法错误

8.2. 异常

8.3. 处理异常

try 语句的工作原理如下。

except (RuntimeError, TypeError, NameError)

如果发生的异常和 except 子句中的类是同一个类或者是它的基类,则异常和 except 子句中的类是兼容的(但反过来则不成立

try:
    f = open(arg, 'r')
except OSError:
    print('cannot open', arg)
else:
    print(arg, 'has', len(f.readlines()), 'lines')
    f.close()

写在 else 和 写在 try 里面的唯一区别就是:写在 else 里面不会尝试 捕捉 f.close() 的异常

8.4. 抛出异常

raise

8.5. 用户自定义异常

8.6. 定义清理操作

def divide(x, y):
    try:
        result = x / y
    except ZeroDivisionError:
        print("division by zero!")
    else:
        print("result is", result)
    finally:
        print("executing finally clause")

finally 子句在任意情况下都会执行

8.7. 预定义的清理操作

with

9. 类

9.1. 名称和对象

9.2. Python 作用域和命名空间

9.2.1. 作用域和命名空间示例

9.3. 初探类

class ClassName:
    <statement-1>
    .
    .
    .
    <statement-N>

9.3.1. 类定义语法

9.3.2. 类对象

9.3.3. 实例对象

9.3.4. 方法对象

9.3.5. 类和实例变量

9.4. 补充说明

9.5. 继承

class DerivedClassName(BaseClassName):
    <statement-1>
    .
    .
    .
    <statement-N>

9.5.1. 多重继承

class DerivedClassName(Base1, Base2, Base3):
    <statement-1>
    .
    .
    .
    <statement-N>

在最简单的情况下,你可以认为搜索从父类所继承属性的操作是深度优先、从左至右的

真实情况比这个更复杂一些;方法解析顺序会动态改变以支持对 super() 的协同调用。 这种方式在某些其他多重继承型语言中被称为后续方法调用,它比单继承型语言中的 super 调用更强大。

动态改变顺序是有必要的,因为所有多重继承的情况都会显示出一个或更多的菱形关联(即至少有一个父类可通过多条路径被最底层类所访问)。 例如,所有类都是继承自 object,因此任何多重继承的情况都提供了一条以上的路径可以通向 object。 为了确保基类不会被访问一次以上,动态算法会用一种特殊方式将搜索顺序线性化, 保留每个类所指定的从左至右的顺序,只调用每个父类一次,并且保持单调(即一个类可以被子类化而不影响其父类的优先顺序)。 总而言之,这些特性使得设计具有多重继承的可靠且可扩展的类成为可能。 要了解更多细节,请参阅 https://www.python.org/download/releases/2.3/mro/。

9.6. 私有变量

9.7. 杂项说明

9.8. 迭代器

class A(object):
    def __iter__(self):
        for i in range(3):
            yield i


if __name__ == '__main__':
    for i in iter(A()):
        print(i)
class A(object):
    def __init__(self):
        self.index = -1

    def __iter__(self):
        return self

    def __next__(self):
        if self.index < 2:
            self.index += 1
            return self.index
        raise StopIteration


if __name__ == '__main__':
    for i in iter(A()):
        print(i)

9.9. 生成器

9.10. 生成器表达式

(i for i in range(10)) # <generator object <genexpr> at 0x102a59410>

10. 标准库简介

10.1. 操作系统接口

10.2. 文件通配符

glob 模块提供了一个在目录中使用通配符搜索创建文件列表的函数:

>>> import glob
>>> glob.glob('*.py')
['primes.py', 'random.py', 'quote.py']

10.3. 命令行参数

10.4. 错误输出重定向和程序终止

10.5. 字符串模式匹配

10.6. 数学

10.7. 互联网访问

10.8. 日期和时间

10.9. 数据压缩

10.10. 性能测量

10.11. 质量控制

10.12. 包含电池

11. 标准库简介 —— 第二部分

11.1. 格式化输出

11.2. 模板

11.3. 使用二进制数据记录格式

11.4. 多线程

11.5. 日志

11.6. 弱引用

11.7. 用于操作列表的工具

11.8. 十进制浮点运算

12. 虚拟环境和包

12.1. 概述

12.2. 创建虚拟环境

12.3. 使用 pip 管理包

13. 接下来

14. 交互式编辑和编辑历史

14.1. Tab 补全和编辑历史

14.2. 默认交互式解释器的替代品

15. 浮点算术:争议和限制

15.1. 表示性错误

16. 附录

16.1. 交互模式

16.1.1. 错误处理

16.1.2. 可执行的 Python 脚本

16.1.3. 交互式启动文件

16.1.4. 定制模块