1. 文件介绍
-
**概述:**文件就是存储在磁盘上的,可以重复使用的数据或者功能集合。
- 将数据存储到磁盘中时,都会以文件为单位保存,叫做数据的持久化。
- 在内存中存储的数据,是以二进制形式存储在内存中的,不是文件。
-
文件操作的步骤:
-
文件操作主要分为读取和写入两类,基本步骤都包含打开文件、操作数据和关闭文件。
-
读取文件
- 打开文件
- 读取数据
- 关闭文件
-
写入文件
- 打开文件
- 写入数据
- 关闭文件
-
2. 文件的读取
-
文件打开:
-
使用
open()
函数打开文件,该函数返回一个file
对象。 -
格式:
open(文件路径, 读写模式, 指定编码集)
-
读写模式:
r
:只读模式,若文件不存在会报错。w
:只写模式,打开文件时会清空原有内容,若文件不存在则会创建新文件。a
:追加模式,文件不会被清空,会在文件末尾追加数据,若文件不存在则会创建新文件。
-
在 Windows 系统下,如果不指定编码集,默认使用
gbk
格式编码。
-
-
文件读取:
文件对象.read(n)
:- 可以指定最大读写字符数,不写
n
表示读取全部内容。 - 如果连续使用
read
读取数据,将会在前一次读取数据的结尾位置继续读取,直到全部读完后返回空字符串。 - 如果关闭文件后再打开,会重新开始从头读取。
- 可以指定最大读写字符数,不写
文件对象.readline()
:读取一行数据,以\n
为读取终点,若没有更多数据则返回空字符串。文件对象.readlines()
:可以一次性读取全部数据,将数据以行为单位进行分割,生成一个列表。
-
**文件关闭:**格式:
文件对象.close()
,文件关闭后不能继续操作文件。 -
代码示例:
file = open('./data/1.txt', 'r', encoding='utf-8') # 读取全部内容 # content = file.read() # print(content) # 读取最多3个字符的内容 # content = file.read(3) # print(content) # content = file.read(3) # print(content) # 读取一行数据 content = file.readline() print(content) content = file.readline() print(content) # 一次性读取全部数据,将数据以行为单位进行分割,生成一个列表 content = file.readlines() print(content) file.close()
3. 文件的写入
-
文件打开:
-
使用
open()
函数打开文件,该函数返回一个file
对象。 -
格式:
open(文件路径, 读写模式, 指定编码集)
-
-
文件写入:
文件对象.write(要写入的内容)
:将指定内容写入文件。文件对象.writelines()
:可将一个包含多行内容的列表写入文件。
-
**文件关闭:**格式:
文件对象.close()
,文件关闭后不能继续操作文件。 -
代码示例:
file = open('./data/2.txt', 'w', encoding='utf-8') file.write("这是要写入的内容。\n") lines = ["第一行\n", "第二行\n", "第三行\n"] file.writelines(lines)
4. 文件的追加
-
代码示例:
file = open('./data/2.txt', 'a', encoding='utf-8') file.write("追加的内容。\n")
5. 文件的读写模式
-
r
:读取模式r
:文本型读取模式rb
:字节型读取模式r+
:文本型读取模式加强,可读写rb+
:字节型读取模式加强,可读写
-
w
:写入模式-
w
:文本型写入模式 -
wb
:字节型写入模式 -
w+
:文本型写入模式加强,可读写 -
wb+
:字节型写入模式加强,可读写
-
-
a
:追加模式a
:文本型追加模式ab
:字节型追加模式a+
:文本型追加模式加强,可读写ab+
:字节型追加模式加强,可读写
6. 异常
-
**概述:**异常就是代码在执行的过程中出现的错误,会造成程序的终止(Error)。
- 异常:程序运行过程中出现的错误,会造成程序的终止运行。
- 警告:程序运行的结果可能和我们预想的不一致,不一定会造成程序的终止。
- 程序从上到下依次运行,当执行到某一行代码出现异常后,会立即终止程序,无法继续执行。
-
常见的异常类型:
NameError
TypeError
ValueError
KeyError
IndexError
-
异常捕获:
-
在开发中,我们一般不希望异常造成程序崩溃,所以我们会使用
try...except
对异常进行捕获。 -
格式:
try: # try必须配合except,不能单独使用 可能出现异常的代码 except: try 中的代码出现异常后将会执行此代码
-
如果
try
中的代码没有出现 异常,则不会执行except
中的代码。 -
如果代码出现异常,程序不会崩溃,会执行
except
中的代码。 -
try
中的代码会从上到下依次运行,当代码出现异常后,不会执行try
中的后续代码,而是直接执行except
中的代码。
-
-
捕获指定类型的异常:
-
概述:在出现异常时,最后一行信息中,冒号之前的是异常类型,冒号之后的是异常信息描述。
-
格式:
try: 可能会出现异常的代码 except 异常类型1: 出现异常类型1执行的代码 except 异常类型2: 出现异常类型2执行的代码 ... # 如果出现的异常不是我们指定的类型中的其中一个,则异常依然会造成程序终止
-
程序中不可能同时出现多个异常,因为一个异常出现,程序就退出了。
-
-
捕获异常描述信息:
-
格式:
try: 可能会出现异常的代码 except 异常类型 as 变量名: print(变量名) # 此时会输出异常信息 except 异常类型 as 变量名: print(变量名) # 此时会输出异常信息
-
-
异常中的
else
:-
格式:
try: 可能出现异常的代码 except: 如果try中的代码出现了异常执行的代码 else: 如果try中的代码没有出现异常时执行的代码
-
-
异常中的
finally
:-
格式:
try: 可能出现异常的代码 except: 如果try中的代码出现了异常执行的代码 else: 如果try中的代码没有出现异常时执行的代码 finally: 无论是否出现异常都会执行的代码
-
-
异常传递:
- 存在异常嵌套的情况下,如果内层
try
没有捕获到异常,可以传递到外层进行捕获,如果外层还是没有捕获到将会继续向外传递,直到程序终止为止。
- 存在异常嵌套的情况下,如果内层
-
代码示例:
# print(a) # NameError: name 'a' is not defined # print(1 + 'a') # TypeError: unsupported operand type(s) for +: 'int' and 'str' # dict1 = {} # print(dict1['name']) # KeyError: 'name' try: print(2 / 1) # 会被执行 print(1 / 0) # 出现异常,直接去执行except中的代码 print(1 / 2) # 不会被执行 except ZeroDivisionError: print("0不能作为除数存在") try: print(a) # NameError print(1 + '2') # TypeError except NameError: print("NameError:出现了变量未定义错误") except TypeError: print("TypeError:出现了类型不一致错误") except Exception: print("出现了未知异常") try: print(1 / 0) print(a) # NameError print(1 + '2') # TypeError except (NameError, TypeError): print("出现了NameError或者TypeError") except Exception as error: print(f"出现了未知异常,{error}") try: print(a) # NameError print(1 + '2') # TypeError except NameError as error: print(error) except TypeError as error: print(error) except Exception as error: print(error) try: print(1 / 0) except: print("出现异常时执行") else: print("未出现异常时执行") try: print(1 / 0) print(1 / 2) except: print("出现异常时执行") else: print("未出现异常时执行") finally: print("无论是否出现异常都会执行") try: print('外层异常') try: print('内层异常') print(1 + '2') except NameError: print('变量没有被定义') except TypeError: print('数据类型错误')
7. 模块
-
**概述:**别人或自己已经写好的功能或者代码,可以通过导入模块的手段进行调用。
-
作用:
- 增加代码的复用率,同一个模块中的功能可以在不同文件或工程中使用 。
- 通过简单的调用实现复杂的功能,降低开发门槛。
- 是多人协同开发的基础。
-
导入方式:
- 全部导入:一次性将模块中所有可以被导入的功能全部导入进去。
- 导入格式:
import 模块名称
- 调用格式:
模块名称.功能名
- 导入格式:
- 局部导入:
- 导入格式:
from 模块名 import 功能名
- 调用格式:
功能名
- 这种方式只能使用导入的功能,未导入的功能不能使用。
- 导入格式:
- 局部导入:
- 导入格式:
from 模块名 import *
- 调用格式:
功能名
- 这种方式还是属于局部导入,因为被导入的功能我们可以手动控制。
- 导入格式:
- 全部导入:一次性将模块中所有可以被导入的功能全部导入进去。
-
给模块或功能起别名:
- 概述:导入模块或者功能时,有些模块名称过长,或者功能层级过多,可以起别名,简化调用过程。
- 给模块起别名:
import 模块 as 别名
- 给功能起别名:
from 模块 import 功能名 as 别名
- 起别名后在当前文件中只能使用别名,原名称失效。
-
自定义模块:
- 自己写的
.py
文件,在导入其他文件内部时,可以直接使用该文件中的功能,这个就是自定义模块。 - 模块名称必须符合标识符命名规则。
- 自己写的
-
__all__
变量:- 在模块中可以在模块开始位置,增加一个
__all__
变量。 - 在这个变量中,存储一个列表,写入到列表中的功能名称,就可以使用
from ... import *
的形式进行一次性导入。 - 如果我们不在模块中书写
__all__
,则使用from ... import *
可以导入全部功能。 - 如果我们在模块中书写
__all__ = []
,则使用from ... import *
无法导入任何功能。 - 如果我们在模块中书写
__all__ = [功能1, 功能2]
,则仅可以使用from ... import *
导入功能1
和功能2
。 __all__
的值不影响全部导入的方式。__all__
的值不影响局部导入中指定功能的方式。
- 在模块中可以在模块开始位置,增加一个
-
代码示例:
# import random # 调用 # print(random.randint(1, 10)) # print(random.random()) # from random import randint # print(randint(1, 100)) # print(random()) # NameError: name 'random' is not defined. Did you forget to import 'random'? # from random import * # # print(randint(1, 100)) # print(random()) # import random as rd # print(rd.randint(1, 10)) # print(random.randint(1, 10)) # NameError: name 'random' is not defined. # from random import randint as rdt # from random import randint as rdt, random as rd # print(rdt(1, 10)) import my_module_01 print(my_module_01.age) my_module_01.func1() my_module_01.func2()
8. 包
-
**概述:**包是一种管理 Python 模块命名空间的方式,采用目录形式组织模块。包目录下必须包含
__init__.py
文件(Python 3.3 之后不是必需的,但为了兼容性建议保留),该文件可以为空,也可包含包的初始化代码或定义__all__
变量。 -
包的导入:
-
导入整个包
import 包名
- 使用包中的模块时,需使用完整的模块路径:
包名.模块名.功能名
。
- 使用包中的模块时,需使用完整的模块路径:
-
导入包中的模块
from 包名 import 模块名
- 使用模块中的功能时,直接使用
模块名.功能名
。
- 使用模块中的功能时,直接使用
-
导入包中模块的功能
from 包名.模块名 import 功能名
- 使用功能时,直接使用
功能名
。
- 使用功能时,直接使用
-
-
__init__.py
文件的作用:- 标识该目录是一个 Python 包。
- 可以在
__init__.py
中编写初始化代码,当包被导入时,这些代码会被执行。 - 可以在
__init__.py
中定义__all__
变量,控制使用from 包名 import *
时导入的模块。
-
代码示例:
假设包名为
my_package
,包含module1.py
和module2.py
两个模块。my_package/__init__.py
:# 可在这里编写初始化代码 __all__ = ['module1', 'module2']
my_package/module1.py
:def func1(): print("这是 module1 中的 func1 函数。")
my_package/module2.py
:def func2(): print("这是 module2 中的 func2 函数。")
在主程序中使用:
# 导入整个包 import my_package my_package.module1.func1() # 导入包中的模块 from my_package import module2 module2.func2() # 导入包中模块的功能 from my_package.module1 import func1 func1()