Python基础知识总结
1. 列表(Lists)
定义与特性
- 有序集合:列表中的元素按照插入顺序排列,每个元素都有一个对应的索引。
- 可变性:列表是可变的,可以在创建后修改其内容,包括添加、删除或更改元素。
- 多样性:列表可以包含不同类型的元素,如整数、字符串、甚至其他列表(嵌套列表)。
创建列表
1 | # 创建一个空列表 |
基本操作
索引和切片
- 索引:通过索引访问特定位置的元素,索引从0开始。支持负索引,从末尾开始计数。
- 切片:通过指定开始和结束索引来获取子列表。
1 | fruits = ['苹果', '香蕉', '橙子', '葡萄', '桃子'] |
添加和删除元素
添加元素:
append(x)
:在列表末尾添加一个元素。insert(i, x)
:在指定位置插入一个元素。extend(iterable)
:将一个可迭代对象的所有元素添加到列表末尾。
删除元素:
remove(x)
:删除列表中第一个匹配的元素。pop([i])
:删除并返回指定位置的元素,默认删除最后一个元素。clear()
:删除列表中的所有元素。
1 | fruits = ['苹果', '香蕉', '橙子'] |
列表推导式
列表推导式是一种简洁的生成列表的方式,通常包含一个表达式和一个或多个 for
循环以及可选的 if
条件。
1 | # 生成0到9的平方列表 |
其他常用方法
index(x)
:返回元素x在列表中第一次出现的索引。count(x)
:返回元素x在列表中出现的次数。sort()
:对列表进行排序。reverse()
:反转列表中的元素。
1 | numbers = [3, 1, 4, 1, 5, 9, 2] |
2. 元组(Tuples)
定义与特性
- 有序集合:元组中的元素按照插入顺序排列,每个元素都有一个对应的索引。
- 不可变性:元组一旦创建,其内容不能修改,包括添加、删除或更改元素。
- 多样性:元组可以包含不同类型的元素,支持嵌套。
创建元组
1 | # 创建一个空元组 |
基本操作
访问元素
- 索引:通过索引访问特定位置的元素,支持负索引。
- 切片:获取子元组。
1 | coordinates = (10, 20, 30, 40) |
不可变性
- 特性:元组一旦创建,不能修改其内容。这使得元组在需要确保数据不被意外修改的场景下非常有用,例如作为字典的键。
- 优点:由于不可变性,元组在某些情况下比列表更高效,尤其是在作为哈希键使用时。
元组的使用场景
多重赋值:
1
2point = (10, 20)
x, y = point函数返回多个值:
1
2
3
4def get_min_max(values):
return (min(values), max(values))
min_val, max_val = get_min_max([3, 1, 4, 1, 5, 9, 2])
其他常用方法
count(x)
:返回元素x在元组中出现的次数。index(x)
:返回元素x在元组中第一次出现的索引。
1 | numbers = (1, 2, 3, 2, 4) |
3. 集合(Sets)
定义与特性
- 无序集合:集合中的元素没有特定的顺序。
- 唯一性:集合中的元素是唯一的,重复的元素会被自动去除。
- 可变性:集合是可变的,可以添加或删除元素。
- 类型限制:集合中的元素必须是可哈希的(即不可变的)。
创建集合
1 | # 创建一个空集合(注意:{} 创建的是空字典) |
基本操作
添加和删除元素
添加元素:
add(x)
:添加一个元素到集合中。update(iterable)
:添加多个元素到集合中。
删除元素:
remove(x)
:删除集合中的元素x,如果x不存在会引发KeyError
。discard(x)
:删除集合中的元素x,如果x不存在不会有任何操作。pop()
:随机删除并返回一个元素。
1 | fruits = {'苹果', '香蕉'} |
集合运算
并集(Union):两个集合的所有元素。
- 运算符:
|
- 方法:
union()
- 运算符:
交集(Intersection):两个集合的共同元素。
- 运算符:
&
- 方法:
intersection()
- 运算符:
差集(Difference):存在于第一个集合但不存在于第二个集合的元素。
- 运算符:
-
- 方法:
difference()
- 运算符:
对称差集(Symmetric Difference):存在于其中一个集合但不同时存在于两个集合中的元素。
- 运算符:
^
- 方法:
symmetric_difference()
- 运算符:
1 | a = {'苹果', '香蕉', '橙子'} |
其他常用方法
issubset(other)
:判断当前集合是否是另一个集合的子集。issuperset(other)
:判断当前集合是否是另一个集合的超集。isdisjoint(other)
:判断两个集合是否没有共同元素。
1 | a = {'苹果', '香蕉'} |
4. 字典(Dictionaries)
定义与特性
- 键值对集合:字典由键(key)和值(value)组成的对组成,每个键与其对应的值相关联。
- 无序集合:字典中的键值对没有特定的顺序(Python 3.7+ 中,字典保持插入顺序)。
- 键的唯一性:每个键在字典中必须是唯一的,值则可以重复。
- 键的不可变性:键必须是不可变的数据类型,如字符串、数字或元组。
创建字典
1 | # 创建一个空字典 |
基本操作
访问与修改
访问值:
- 通过键访问对应的值,使用
dict[key]
或dict.get(key)
方法。 get(key, default)
方法可以在键不存在时返回默认值,而不会引发错误。
- 通过键访问对应的值,使用
修改值:
- 通过键直接赋值,添加或更新键值对。
删除键值对:
- 使用
del dict[key]
删除特定键。 - 使用
pop(key)
删除特定键并返回其值。 - 使用
clear()
删除所有键值对。
- 使用
1 | person = {'姓名': '张三', '年龄': 30} |
字典方法
keys()
:返回字典中所有键的视图。values()
:返回字典中所有值的视图。items()
:返回字典中所有键值对的视图。update(other)
:将另一个字典或键值对序列合并到当前字典中。copy()
:返回字典的浅拷贝。
1 | person = {'姓名': '张三', '年龄': 30, '城市': '北京'} |
字典推导式
类似于列表推导式,字典推导式用于通过某种逻辑生成字典。
1 | # 生成一个数字及其平方的字典 |
5. 序列操作(Sequence Operations)
通用操作
Python 提供了一组通用函数,可以应用于所有序列类型(如列表、元组、字符串等)。
len(s)
:返回序列的长度。max(s)
:返回序列中的最大值。min(s)
:返回序列中的最小值。sorted(s)
:返回一个排序后的新列表。reversed(s)
:返回一个反向迭代器。
1 | fruits = ['苹果', '香蕉', '橙子'] |
成员测试
使用 in
和 not in
运算符检查元素是否存在于序列中。
1 | fruits = ['苹果', '香蕉', '橙子'] |
连接与重复
- 连接:使用
+
运算符连接两个序列。 - 重复:使用
*
运算符重复序列。
1 | a = [1, 2, 3] |
6. 列表推导式(List Comprehensions)
定义与用法
列表推导式是一种简洁且高效的方法,用于根据已有的可迭代对象生成新列表。它由一个表达式和一个或多个 for
循环组成,并可包含条件筛选。
1 | # 基本语法 |
示例
生成平方数列表:
1
squares = [x**2 for x in range(10)] # [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
筛选偶数:
1
even_squares = [x**2 for x in range(10) if x % 2 == 0] # [0, 4, 16, 36, 64]
嵌套循环:
1
2pairs = [(x, y) for x in range(3) for y in range(3)]
# [(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2), (2, 0), (2, 1), (2, 2)]
嵌套推导式
列表推导式可以嵌套使用,用于生成多维列表或更复杂的数据结构。
1 | # 生成一个3x3的矩阵 |
优势
- 简洁:相比传统的
for
循环,列表推导式代码更简洁。 - 高效:列表推导式在执行速度上通常比等效的循环更快。
注意事项
- 可读性:过于复杂的列表推导式可能影响代码的可读性,建议在逻辑简单时使用,复杂时采用传统循环。
- 嵌套深度:避免过多嵌套,以免代码难以理解。
7. 嵌套数据结构(Nested Data Structures)
多层嵌套
Python 的数据结构(如列表、元组、字典、集合)可以相互嵌套,形成复杂的数据层次,适用于存储和处理复杂的数据关系。
1 | # 列表嵌套 |
访问嵌套元素
通过多级索引或键访问内部元素。
1 | # 访问嵌套列表 |
应用场景
- 数据库记录:模拟数据库中的表和记录。
- 配置文件:存储多层次的配置选项。
- 数据分析:处理和组织复杂的数据集。
8. 其他数据结构
集合推导式(Set Comprehensions)
类似于列表推导式,集合推导式用于生成集合,保证元素的唯一性。
1 | # 生成一个包含0到9平方的集合 |
字典推导式(Dictionary Comprehensions)
用于通过某种逻辑生成字典,包含键和值的表达式。
1 | # 生成一个数字及其平方的字典 |
9. 数据结构的选择
适用场景
选择合适的数据结构对编写高效、可维护的代码至关重要。以下是常见数据结构的适用场景:
列表(Lists):
- 特点:有序、可变、允许重复元素。
- 适用场景:需要按顺序存储元素并频繁进行添加、删除操作的场景,如任务列表、动态数据集合。
元组(Tuples):
- 特点:有序、不可变、允许重复元素。
- 适用场景:需要固定数据集合,确保数据不被修改的场景,如函数返回多个值、字典的键。
集合(Sets):
- 特点:无序、唯一、不重复。
- 适用场景:需要去重、进行集合运算(如并集、交集)的场景,如用户标签、权限管理。
字典(Dictionaries):
- 特点:键值对存储、无序(保持插入顺序)、键唯一。
- 适用场景:需要快速查找、关联数据的场景,如配置选项、数据库记录。
性能考虑
访问速度:
- 列表:按索引访问速度快,但查找元素需要线性时间。
- 字典和集合:基于哈希表,查找、插入和删除操作平均时间复杂度为O(1)。
内存使用:
- 列表和元组:内存占用较低,尤其是元组因不可变性更为紧凑。
- 字典和集合:由于需要存储哈希值,内存占用相对较高。
可变性与不可变性
- 可变数据结构(如列表、字典、集合)适用于需要频繁修改数据的场景。
- 不可变数据结构(如元组)适用于需要确保数据不被修改或作为哈希键的场景。
模块(Modules)
1. 模块的定义与导入
定义
- 模块是一个包含Python定义和语句的文件。模块可以定义函数、类和变量,还可以包含可执行的代码。
- 通过模块,可以组织和重用代码,促进代码的模块化和维护性。
导入模块
- 使用
import
语句导入模块。 - 语法:
1
import module_name
- 例子:
1
2import math
print(math.sqrt(16)) # 输出: 4.0
从模块中导入特定部分
- 使用
from ... import ...
语句。 - 语法:
1
from module_name import function_name
- 例子:
1
2from math import sqrt
print(sqrt(25)) # 输出: 5.0
导入所有内容
- 使用
from module_name import *
导入模块的所有公共属性和方法。 - 例子:
1
2
3from math import *
print(pi) # 输出: 3.141592653589793
print(sin(0)) # 输出: 0.0 - 注意:不推荐使用
import *
,因为它可能导致命名冲突,降低代码可读性。
使用别名
- 使用
as
关键字为模块或导入的部分指定别名。 - 例子:
1
2
3
4
5import math as m
print(m.sqrt(9)) # 输出: 3.0
from math import sqrt as square_root
print(square_root(16)) # 输出: 4.0
2. 模块搜索路径
搜索顺序
当导入模块时,Python解释器会按照以下顺序搜索模块:
- 当前目录:首先在当前脚本所在的目录查找模块。
- **环境变量
PYTHONPATH
**:如果设置了PYTHONPATH
,则在该路径下搜索。 - 标准库目录:搜索Python安装目录下的标准库模块。
- 第三方库目录:搜索安装的第三方库模块。
查看搜索路径
- 使用
sys
模块的sys.path
属性查看当前的模块搜索路径。 - 例子:
1
2import sys
print(sys.path)
修改搜索路径
- 可以在运行时通过修改
sys.path
来添加新的搜索路径。 - 例子:
1
2import sys
sys.path.append('/path/to/your/module')
3. 标准模块
标准库概述
- Python提供了丰富的标准库模块,涵盖了文件操作、系统调用、网络编程、数据处理等多个领域。
- 常用标准模块包括
sys
,os
,math
,datetime
,json
,re
等。
例子:使用 datetime
模块
1 | import datetime |
4. 创建模块
创建一个简单模块
- 创建一个Python文件,例如
mymodule.py
,并定义一些函数和变量。1
2
3
4
5
6# mymodule.py
def greet(name):
return f"Hello, {name}!"
pi = 3.141592653589793 - 在另一个脚本中导入并使用该模块。
1
2
3
4import mymodule
print(mymodule.greet("Alice")) # 输出: Hello, Alice!
print(mymodule.pi) # 输出: 3.141592653589793
模块的命名空间
- 每个模块都有自己的命名空间,模块内部的变量不会影响其他模块,反之亦然。
- 可以使用
dir()
函数查看模块的属性。1
2import mymodule
print(dir(mymodule))
5. 包(Packages)
定义
- 包是一种组织模块的方式,使用文件夹和
__init__.py
文件实现。 - 包可以包含子包和模块,形成层级结构。
创建包
创建一个文件夹,例如
mypackage
,并在其中添加一个__init__.py
文件(可以为空)。在
mypackage
文件夹中添加模块文件,例如module1.py
和module2.py
。1
2
3
4mypackage/
__init__.py
module1.py
module2.py导入包中的模块:
1
2from mypackage import module1
from mypackage.module2 import some_function
相对导入
- 在包内部,可以使用相对导入来引用同一包中的其他模块。
- 使用
.
表示当前包,..
表示上级包。1
2
3# 在 mypackage/module1.py 中
from . import module2
from .module2 import some_function
6. 模块的命名空间
全局变量与局部变量
- 模块的全局变量在整个模块中可见。
- 在函数或类内部定义的变量是局部变量,仅在其作用范围内可见。
__name__
变量
每个模块都有一个特殊变量
__name__
,表示模块的名称。当模块被直接运行时,
__name__
的值为'__main__'
。当模块被导入时,
__name__
的值为模块的实际名称。1
2
3
4
5# mymodule.py
if __name__ == "__main__":
print("模块被直接运行")
else:
print("模块被导入")
7. from-import 语句
基本用法
- 从模块中导入特定的属性或方法,避免使用模块前缀。
1
2
3from math import sqrt, pi
print(sqrt(16)) # 输出: 4.0
print(pi) # 输出: 3.141592653589793
导入所有内容
- 使用
from module import *
导入模块的所有公共属性和方法。1
2from math import *
print(sin(0)) # 输出: 0.0 - 注意:这种方式可能导致命名冲突,需谨慎使用。
为导入的属性指定别名
- 使用
as
关键字为导入的属性指定别名。1
2from math import sqrt as square_root
print(square_root(25)) # 输出: 5.0
8. 动态导入模块
使用 __import__
函数
- 可以在运行时动态导入模块,适用于需要根据变量导入不同模块的情况。
1
2
3module_name = "math"
math_module = __import__(module_name)
print(math_module.sqrt(9)) # 输出: 3.0
使用 importlib
模块
- 更现代和灵活的动态导入方式。
1
2
3
4
5import importlib
module_name = "math"
math_module = importlib.import_module(module_name)
print(math_module.pi) # 输出: 3.141592653589793
9. 模块的生命周期
导入模块时的执行过程
- 当模块被首次导入时,Python会执行模块中的所有顶层代码,并将模块对象存储在
sys.modules
中。 - 后续导入相同模块时,不会重新执行模块代码,而是直接从
sys.modules
中获取模块对象。
模块的缓存
sys.modules
是一个字典,保存了所有已导入的模块。它可以用于检查模块是否已被导入,或动态修改模块。1
2
3
4import sys
import math
print('math' in sys.modules) # 输出: True
10. 编写可重用的代码
模块化编程的优势
- 代码重用:将常用功能封装在模块中,便于多处使用。
- 命名空间隔离:避免不同模块之间的命名冲突。
- 可维护性:模块化代码更易于理解和维护。
示例:创建一个工具模块
1 | # utils.py |
1 | # main.py |
11. 内建模块(Built-in Modules)
概述
- Python提供了许多内建模块,随解释器一起分发,无需额外安装即可使用。
- 常用内建模块包括
sys
,os
,math
,datetime
,json
,re
,random
等。
示例:使用 random
模块
1 | import random |
12. 模块的高级特性
包的相对导入
- 在包内部,可以使用相对导入来引用同一包中的其他模块。
- 示例结构:
1
2
3
4
5
6mypackage/
__init__.py
module1.py
subpackage/
__init__.py
module2.py - 在
module2.py
中导入module1
:1
from .. import module1
动态修改模块
- 可以在运行时添加、删除或修改模块的属性。
1
2
3import math
math.new_attribute = "新的属性"
print(math.new_attribute) # 输出: 新的属性
模块的生命周期管理
- 使用
importlib.reload()
可以重新加载模块,适用于开发过程中需要更新模块内容的场景。1
2
3
4import importlib
import mymodule
importlib.reload(mymodule)
13. __main__
模块
定义
- 当模块被直接运行时,
__name__
变量被设置为'__main__'
。 - 这使得模块可以区分是被导入还是被直接运行,从而执行不同的代码逻辑。
示例
1 | # mymodule.py |
1 | # 直接运行模块 |
14. 小结
模块是Python中组织和重用代码的基本单元。通过模块化编程,可以提高代码的可维护性、可读性和复用性。理解模块的导入机制、搜索路径、命名空间以及包的结构,是高效编写Python程序的关键。
15. 实践建议
- 合理组织代码:将相关功能封装在模块和包中,避免模块过于庞大。
- 使用有意义的命名:为模块和包选择描述性强的名称,便于理解和使用。
- 遵循PEP 8:遵循Python的编码规范(PEP 8),保持代码一致性和可读性。
- 避免循环依赖:模块之间尽量减少相互依赖,避免复杂的循环导入关系。
- 利用标准库:在编写新模块前,先查找是否已有标准库模块或第三方库能够满足需求。
输入与输出(Input and Output)
更复杂的输出格式
在 Python 中,除了基本的 print()
函数外,还有多种方法可以实现更复杂和灵活的输出格式,包括格式化字符串字面值(f-strings)、str.format()
方法、手动格式化字符串以及旧式的字符串格式化方法。
格式化字符串字面值(f-strings)
定义与特性:
- 从 Python 3.6 开始引入的字符串格式化方法,使用前缀
f
或F
。 - 允许在字符串中嵌入表达式,表达式放在花括号
{}
内。
示例:
1 | name = "Alice" |
优势:
- 语法简洁,易读性强。
- 支持表达式计算,可以直接在字符串中进行计算和调用函数。
字符串 format()
方法
定义与用法:
- 使用花括号
{}
作为占位符,通过str.format()
方法插入变量。 - 支持位置参数和关键字参数。
示例:
1 | name = "Bob" |
格式说明符:
- 可以在花括号内添加格式说明符,如指定宽度、对齐方式、小数位数等。
1
2
3pi = 3.14159
print("圆周率约为 {:.2f}".format(pi))
# 输出: 圆周率约为 3.14
手动格式化字符串
定义与用法:
- 通过字符串的拼接或转换,将变量手动插入到字符串中。
- 使用
+
运算符或,
分隔符。
示例:
1 | name = "Eve" |
注意事项:
- 需要手动转换非字符串类型为字符串。
- 代码可能较为冗长,可读性较低。
旧式字符串格式化方法
定义与用法:
- 使用
%
运算符进行字符串格式化。 - 类似于 C 语言中的
printf
风格。
示例:
1 | name = "Frank" |
注意事项:
- 虽然仍然被支持,但不推荐在新代码中使用,因为
str.format()
和 f-strings 提供了更强大的功能和更好的可读性。
读写文件
Python 提供了多种方法来读取和写入文件,包括文本文件和二进制文件的操作,以及使用 JSON 保存结构化数据。
文件对象的方法
打开文件:
- 使用
open()
函数打开文件,返回文件对象。 - 常用模式包括读取
'r'
、写入'w'
、追加'a'
,以及二进制模式'rb'
,'wb'
等。
示例:
1 | # 以读取模式打开文件 |
常用方法:
read(size=-1)
:读取指定大小的内容,默认读取全部内容。1
2
3with open('example.txt', 'r', encoding='utf-8') as f:
content = f.read()
print(content)readline()
:读取文件的一行内容。1
2
3
4
5with open('example.txt', 'r', encoding='utf-8') as f:
line = f.readline()
while line:
print(line, end='')
line = f.readline()readlines()
:读取文件的所有行,返回一个列表。1
2
3
4with open('example.txt', 'r', encoding='utf-8') as f:
lines = f.readlines()
for line in lines:
print(line, end='')write(string)
:将字符串写入文件。1
2
3with open('example.txt', 'w', encoding='utf-8') as f:
f.write('Hello, World!\n')
f.write('这是一个示例文件。\n')writelines(lines)
:将一个字符串列表写入文件,不自动添加换行符。1
2
3lines = ['第一行\n', '第二行\n', '第三行\n']
with open('example.txt', 'w', encoding='utf-8') as f:
f.writelines(lines)
使用 with
语句管理文件:
- 使用
with
语句可以自动管理文件资源,确保文件在使用完毕后正确关闭,即使发生异常也能保证关闭文件。 - 示例:
1
2
3with open('example.txt', 'r', encoding='utf-8') as f:
content = f.read()
print(content)
文件模式:
'r'
:只读模式,文件指针放在文件开头。'rb'
:二进制读取模式。'w'
:写入模式,会覆盖已有文件。'wb'
:二进制写入模式。'a'
:追加模式,文件指针放在文件末尾。'ab'
:二进制追加模式。'r+'
:读写模式,文件指针放在开头。'w+'
:写读模式,会覆盖文件。'a+'
:追加读写模式。
文件指针操作:
tell()
:返回文件指针的当前位置(以字节为单位)。1
2
3
4with open('example.txt', 'r', encoding='utf-8') as f:
f.read(10)
position = f.tell()
print(f"当前文件指针位置:{position}")seek(offset, whence)
:移动文件指针到指定位置。offset
:偏移量。whence
:参考点,0
表示文件开头,1
表示当前位置,2
表示文件末尾。1
2
3
4with open('example.txt', 'r', encoding='utf-8') as f:
f.seek(5) # 移动到第6个字节
data = f.read(10)
print(data)
使用 JSON 保存结构化数据
定义与用途:
- JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,易于人阅读和编写,同时也易于机器解析和生成。
- 适用于保存和传输结构化数据,如配置文件、数据存储等。
Python 中的 JSON 模块:
- Python 提供了内置的
json
模块,用于处理 JSON 数据的编码和解码。
常用函数:
json.dump(obj, fp, ...)
:将 Python 对象编码为 JSON 格式,并写入文件对象fp
。1
2
3
4
5
6
7
8
9
10
11import json
data = {
'name': 'Alice',
'age': 30,
'city': 'Beijing',
'interests': ['reading', 'traveling']
}
with open('data.json', 'w', encoding='utf-8') as f:
json.dump(data, f, ensure_ascii=False, indent=4)json.load(fp, ...)
:从文件对象fp
中读取 JSON 数据,并解码为 Python 对象。1
2
3
4
5
6import json
with open('data.json', 'r', encoding='utf-8') as f:
data = json.load(f)
print(data)
# 输出: {'name': 'Alice', 'age': 30, 'city': 'Beijing', 'interests': ['reading', 'traveling']}json.dumps(obj, ...)
:将 Python 对象编码为 JSON 字符串。1
2
3
4
5
6import json
data = {'name': 'Bob', 'age': 25}
json_str = json.dumps(data)
print(json_str)
# 输出: {"name": "Bob", "age": 25}json.loads(s, ...)
:将 JSON 字符串解码为 Python 对象。1
2
3
4
5
6import json
json_str = '{"name": "Charlie", "age": 28}'
data = json.loads(json_str)
print(data)
# 输出: {'name': 'Charlie', 'age': 28}
参数说明:
ensure_ascii
:默认为True
,确保输出的所有字符都是 ASCII 字符。设为False
可输出非 ASCII 字符。indent
:设置缩进级别,使输出的 JSON 更加美观和易读。
示例:保存和读取复杂数据结构:
1 | import json |
输出:
1 | { |
注意事项:
- JSON 支持的数据类型有限,主要包括对象(字典)、数组(列表)、字符串、数字、布尔值和
null
。不支持自定义对象或复杂数据类型,需先转换为可序列化的格式。 - 使用
json
模块时,确保数据结构中所有键和值都是 JSON 支持的类型。
读写二进制文件
除了文本文件,Python 还支持二进制文件的读写操作,适用于处理图片、音频、视频等非文本数据。
读取二进制文件:
1 | with open('image.png', 'rb') as f: |
写入二进制文件:
1 | with open('copy_image.png', 'wb') as f: |
注意事项:
- 在二进制模式下,读写的是字节对象(
bytes
),而不是字符串。 - 处理二进制数据时,需要注意编码和解码问题,确保数据的正确性。
文件对象的方法
常用方法概览:
read(size=-1)
:读取指定大小的内容,默认读取全部内容。readline(size=-1)
:读取一行内容。readlines(hint=-1)
:读取所有行,返回列表。write(string)
:写入字符串。writelines(lines)
:写入字符串列表。seek(offset, whence=0)
:移动文件指针。tell()
:返回文件指针当前位置。flush()
:刷新缓冲区,将数据写入文件。close()
:关闭文件。
示例:
1 | # 读取文件内容 |
使用 with
语句:
- 自动管理文件资源,确保文件在使用完毕后关闭。
1
2
3with open('example.txt', 'r', encoding='utf-8') as f:
for line in f:
print(line, end='')
总结
Python 的输入与输出操作功能强大且灵活,涵盖了从简单的打印信息到复杂的文件读写操作、数据格式化以及结构化数据处理。通过掌握以下关键点,可以有效地处理各种 I/O 需求:
文件操作:
- 使用
open()
函数以不同模式打开文件。 - 通过
read()
,readline()
,readlines()
,write()
,writelines()
等方法进行文件内容的读取和写入。 - 使用
with
语句自动管理文件资源,确保文件正确关闭。 - 处理文件指针的移动和当前位置的获取。
- 使用
输出格式化:
- 使用
print()
函数进行基本输出。 - 利用 f-strings、
str.format()
方法实现复杂和灵活的字符串格式化。 - 了解手动格式化和旧式格式化方法,但推荐使用 f-strings 或
str.format()
。
- 使用
处理结构化数据:
- 使用
json
模块读取和写入 JSON 数据,适用于配置文件和数据交换。 - 理解 JSON 的数据类型限制,确保数据可序列化。
- 使用
读写二进制文件:
- 了解如何以二进制模式打开和处理文件,适用于非文本数据。
理解并灵活运用这些输入与输出的方法和技巧,能够显著提升 Python 程序的功能性和用户体验。
类
Python 支持面向对象编程(OOP),允许开发者使用类和对象来组织和管理代码。类是创建对象的蓝图,通过类可以封装数据和功能,促进代码的复用性和可维护性。
名称和对象
在 Python 中,一切皆对象。类本身也是对象,具有自己的属性和方法。每个对象都有一个唯一的身份(ID)、类型(type)和一个值(value)。
- 名称:名称是指向对象的引用,类似于变量名。名称绑定到对象,而不是对象绑定到名称。
- 对象:对象是类的实例,拥有类定义的属性和方法。
示例:
1 | class Dog: |
Python 作用域和命名空间
作用域(Scope)和命名空间(Namespace)是理解变量解析和访问权限的关键概念。
作用域和命名空间示例
- 局部作用域:函数或方法内部定义的命名空间。
- 全局作用域:模块级别的命名空间。
- 内建作用域:Python 解释器启动时创建的命名空间,包含内置函数和异常。
示例:
1 | x = "全局变量" |
初探类
类是创建对象的蓝图,定义了对象的属性和行为。通过类,可以创建多个实例,每个实例都有自己的属性值。
类定义语法
使用 class
关键字定义类,类名通常采用大驼峰命名法。
示例:
1 | class Dog: |
Class 对象
类本身也是对象,属于 type
类型。可以动态地为类添加属性和方法。
示例:
1 | class MyClass: |
实例对象
实例对象是根据类创建的具体对象,拥有类定义的属性和方法。
示例:
1 | my_dog = Dog('Willie', 6) |
方法对象
方法是类中的函数,定义了对象的行为。方法的第一个参数通常为 self
,代表实例本身。
示例:
1 | class Cat: |
类和实例变量
- 类变量:属于类本身,所有实例共享。定义在类体中,但不在任何方法内。
- 实例变量:属于每个实例,互不影响。通常在
__init__
方法中通过self
定义。
示例:
1 | class Bird: |
补充说明
特殊方法
类中可以定义特殊方法(如 __init__
, __str__
, __repr__
等)来定制对象的行为。这些方法以双下划线开头和结尾,具有特定的用途。
示例:
1 | class Point: |
描述符
描述符是实现了 __get__
, __set__
, __delete__
方法的类,用于管理属性访问。
示例:
1 | class Descriptor: |
属性(Properties)
使用 @property
装饰器将方法转换为属性,实现属性的获取、设置和删除操作,增强封装性。
示例:
1 | class Temperature: |
继承
继承是面向对象编程的核心概念之一,允许子类继承父类的属性和方法,实现代码复用和扩展。
多重继承
一个子类可以继承多个父类,形成多重继承关系。Python 使用方法解析顺序(MRO)来确定方法和属性的搜索顺序。
示例:
1 | class Mother: |
私有变量
通过命名约定控制属性和方法的访问权限,增强封装性和数据保护。
命名约定
- **单前导下划线
_
**:表示受保护的属性或方法,建议内部使用,外部不直接访问。 - **双前导下划线
__
**:触发名称重整(Name Mangling),使属性在类外部难以访问。
示例:
1 | class MyClass: |
使用 property
控制访问
通过 @property
装饰器和相应的装饰器控制属性的访问和修改,提供更好的封装。
示例:
1 | class BankAccount: |
杂项说明
方法装饰器
除了 @property
,还有其他方法装饰器如 @classmethod
和 @staticmethod
,用于定义类方法和静态方法。
示例:
1 | class MyClass: |
动态添加属性和方法
类和实例在运行时可以动态添加属性和方法,增强灵活性。
示例:
1 | class Dynamic: |
迭代器
类可以实现迭代器协议,使其实例能够在 for
循环中使用。迭代器需要实现 __iter__
和 __next__
方法。
示例:
1 | class MyIterator: |
生成器
生成器是一种简化迭代器创建的方法,通过 yield
关键字生成值。生成器使代码更简洁,节省内存。
示例:
1 | def my_generator(limit): |
生成器表达式
生成器表达式是一种简洁的生成器的语法,类似于列表推导式,但使用圆括号 ()
。
示例:
1 | gen = (x**2 for x in range(5)) |
总结
Python 的类机制提供了强大的面向对象编程支持,使代码组织、复用和扩展变得更加容易。通过理解和掌握以下关键点,可以高效地使用类来构建复杂的应用程序:
- 名称和对象:理解名称与对象的关系,掌握作用域和命名空间的概念。
- 类的定义与实例化:使用
class
关键字定义类,通过构造方法__init__
初始化实例属性。 - 类和实例变量:区分类变量与实例变量,理解它们的共享和独立性。
- 方法对象:掌握实例方法、类方法和静态方法的定义与使用。
- 继承与多重继承:通过继承实现代码复用,理解方法解析顺序(MRO)。
- 私有变量:通过命名约定和
property
控制属性的访问权限,增强封装性。 - 迭代器与生成器:实现迭代器协议,使用生成器简化迭代器创建。
- 高级特性:如描述符、属性、动态添加属性和方法等,提升类的灵活性和功能性。
理解并灵活运用这些类的特性和方法,能够显著提升 Python 程序的组织性、可维护性和功能性。