【Python学习】(认识函数、列表、元组、字典与文件核心知识要点)

作者:承渊政道日期:2026/7/16

🔥承渊政道:个人主页

❄️个人专栏: 《C语言基础语法知识》 《数据结构与算法》 《C++知识内容》 《Linux系统知识》 《算法刷题指南》 《测评文章活动推广》 《大模型语言路线学习》 《MySQL数据库学习》 《Python知识内容》

✨逆境不吐心中苦,顺境不忘来时路!✨

🎬 博主简介:

在学习 Python 的过程中,掌握基础语法只是第一步,真正决定代码是否清晰、高效、易维护的,是对函数、列表、元组、字典以及文件操作等核心知识的理解.函数可以帮助我们封装重复逻辑,让代码结构更加清晰;列表、元组和字典是 Python 中最常用的数据容器,分别适合处理不同类型的数据;文件操作则让程序能够读取、保存和管理外部数据,使代码从简单练习逐渐走向实际应用.本文将围绕函数、列表、元组、字典与文件操作展开,通过基础概念、语法结构和简单示例,梳理这些知识点之间的区别与使用场景.无论你是刚开始学习 Python,还是想重新巩固基础,都可以通过本文建立更加完整、清晰的知识框架.废话不多说,下面跟着小编的节奏🎵一起去疯狂的学习吧!

目录

  • 1.函数
    • 1.1函数是什么
    • 1.2语法格式
    • 1.3函数参数
    • 1.4函数返回值
    • 1.5变量作用域
    • 1.6函数执行过程
    • 1.7链式调用
    • 1.8嵌套调用
    • 1.9函数递归
    • 1.10参数默认值
    • 1.11关键字参数
  • 2.列表和元组
    • 2.1列表是什么,元组是什么
    • 2.2创建列表
    • 2.3访问下标
    • 2.4切片操作
    • 2.5遍历列表元素
    • 2.6新增元素
    • 2.7查找元素
    • 2.8删除元素
    • 2.9连接列表
    • 2.10关于元组
  • 3.字典
    • 3.1字典是什么
    • 3.2创建字典
    • 3.3查找 key
    • 3.4新增/修改元素
    • 3.5删除元素
    • 3.6遍历字典元素
    • 3.7取出所有 key 和 value
    • 3.8合法的 key 类型
  • 4.文件
    • 4.1文件是什么
    • 4.2文件路径
    • 4.3文件操作
      • 4.3.1打开文件
        • 4.3.2关闭文件
        • 4.3.3写文件
        • 4.3.4读文件
    • 4.4关于中文的处理
    • 4.5使用上下文管理器

1.函数

1.1函数是什么

编程中的函数和数学中的函数有一定的相似之处. 数学上的函数, 比如 y = sin x , x 取不同的值, y 就会得到不同的结果. 编程中的函数, 是一段 可以被重复使用的代码片段 .

代码示例: 求数列的和, 不使用函数

1# 1.  1 - 100 的和
2sum = 0
3for i in range(1, 101):
4sum += i
5print(sum)
6
7# 2.  300 - 400 的和
8sum = 0
9for i in range(300, 401):
10sum += i
11print(sum)
12
13# 3.  1 - 1000 的和
14sum = 0
15for i in range(1, 1001):
16sum += i
17print(sum)
18

可以发现, 这几组代码基本是相似的, 只有一点点差异. 可以把重复代码提取出来, 做成一个函数.实际开发中,复制粘贴是一种不太好的策略.实际开发的重复代码可能存在几十份甚至上百份.一旦这个重复代码需要被修改,那就得改几十次,非常不便于维护.

代码示例: 求数列的和,使用函数

1# 定义函数
2def calcSum(beg, end):
3sum = 0
4for i in range(beg, end + 1):
5sum += i
6print(sum)
7# 调用函数
8sum(1, 100)
9sum(300, 400)
10sum(1, 1000)
11

可以明显看到,重复的代码已经被消除了.


1.2语法格式

创建函数/定义函数

1def 函数名(形参列表):
2函数体
3return 返回值
4

调用函数/使用函数

1函数名(实参列表) // 不考虑返回值
2返回值 = 函数名(实参列表) // 考虑返回值
3

函数定义并不会执行函数体内容, 必须要调用才会执行. 调用几次就会执行几次

1def test1():
2print('hello')
3# 如果光是定义函数, 而不调用, 则不会执行.
4

函数必须先定义, 再使用.

1test3() # 还没有执行到定义, 就先执行调用了, 此时就会报错.
2def test3():
3print('hello')
4

1.3函数参数

在函数定义的时候,可以在( )中指定"形式参数"(简称形参),然后在调用的时候,由调用者把"实际参数"(简称实参)传递进去.这样就可以做到一份函数,针对不同的数据进行计算处理.
考虑前面的代码案例:

1def calcSum(beg, end):
2sum = 0
3for i in range(beg, end + 1):
4sum += i
5print(sum)
6calcSum(1, 100)
7calcSum(300, 400)
8calcSum(1, 1000)
9

上面的代码中,beg, end 就是函数的形参.1,100/300,400就是函数的实参.
(1)在执行sum(1,100) 的时候,就相当于beg=1,end=100,然后在函数内部就可以针对1-100进行运算.
(2)在执行sum(300, 400) 的时候,就相当于beg=300,end=400 ,然后在函数内部就可以针对300-400进行运算.

注意:
一个函数可以有一个形参,也可以有多个形参,也可以没有形参.
一个函数的形参有几个,那么传递实参的时候也得传几个.保证个数要匹配.

1def test(a, b, c):
2	print(a, b, c)
3test(10)
4


和C++/Java不同,Python是动态类型的编程语言,函数的形参不必指定参数类型.换句话说,一个
函数可以支持多种不同类型的参数.

1def test(a):
2	print(a)
3test(10)
4test('hello')
5test(True)
6


1.4函数返回值

函数的参数可以视为是函数的"输入",则函数的返回值,就可以视为是函数的"输出".
此处的"输入","输出"是更广义的输入输出,不是单纯指通过控制台输入输出.
我们可以把函数想象成一个 “工厂”.工厂需要买入原材料,进行加工,并生产出产品.
函数的参数就是原材料, 函数的返回值就是生产出的产品

1def calcSum(beg, end):
2	sum = 0
3	for i in range(beg, end + 1):
4		sum += i
5	print(sum)
6calcSum(1, 100)
7

可以转换成

1def calcSum(beg, end):
2sum = 0
3for i in range(beg, end + 1):
4sum += i
5return sum
6result = calcSum(1, 100)
7print(result)
8

这两个代码的区别就在于,前者直接在函数内部进行了打印,后者则使用 return 语句把结果返回给函数调用者,再由调用者负责打印.我们一般倾向于第二种写法.实际开发中我们的一个通常的编程原则, 是"逻辑和用户交互分离".而第一种写法的函数中,既包含了计算逻辑,又包含了和用户交互(打印到控制台上).这种写法是不太好的,如果后续我们需要的是把计算结果保存到文件中,或者通过网络发送,或者展示到图形化界面里,那么第一种写法的函数,就难以胜任了.而第二种写法则专注于做计算逻辑,不负责和用户交互.那么就很容易把这个逻辑搭配不同的用户交
互代码,来实现不同的效果.

一个函数中可以有多个 return 语句

1# 判定是否是奇数
2def isOdd(num):
3if num % 2 == 0:
4return False
5else:
6return True
7result = isOdd(10)
8print(result)
9

执行到return语句,函数就会立即执行结束,回到调用位置.

1# 判定是否是奇数
2def isOdd(num):
3if num % 2 == 0:
4return False
5return True
6result = isOdd(10)
7print(result)
8

如果num是偶数,则进入if之后,就会触发return False ,也就不会继续执行 return True
一个函数是可以一次返回多个返回值的.使用,来分割多个返回值.

1def getPoint():
2	x = 10
3	y = 20
4return x, y
5a, b = getPoint()
6

如果只想关注其中的部分返回值,可以使用 _ 来忽略不想要的返回值.

1def getPoint():
2	x = 10
3	y = 20
4	return x, y
5_, b = getPoint()
6

1.5变量作用域

1def getPoint():
2	x = 10
3	y = 20
4	return x, y
5x, y = getPoint()
6

在这个代码中,函数内部存在x, y,函数外部也有 x, y.
但是这两组x, y不是相同的变量,而只是恰好有一样的名字.

变量只能在所在的函数内部生效.
在函数getPoint() 内部定义的 x, y 只是在函数内部生效.一旦出了函数的范围,这两个变量就不再生效了.

1def getPoint():
2	x = 10
3	y = 20
4	return x, y
5getPoint()
6print(x, y)
7


在不同的作用域中,允许存在同名的变量
虽然名字相同,实际上是不同的变量.

1x = 20
2def test():
3	x = 10
4	print(f'函数内部 x = {x}')
5test()
6print(f'函数外部 x = {x}')
7


注意:
在函数内部的变量,也称为 “局部变量”
不在任何函数内部的变量,也称为 “全局变量”

如果函数内部尝试访问的变量在局部不存在,就会尝试去全局作用域中查找

1x = 20
2def test():
3	print(f'x = {x}')
4test()
5


如果是想在函数内部,修改全局变量的值,需要使用global关键字声明

1x = 20
2def test():
3	global x
4	x = 10
5	print(f'函数内部 x = {x}')
6test()
7print(f'函数外部 x = {x}')
8


如果此处没有global,则函数内部的x =10就会被视为是创建一个局部变量x,这样就和全局变量 x 不相关了.

if / while / for 等语句块不会影响到变量作用域
换而言之,在 if / while / for 中定义的变量,在语句外面也可以正常使用.

1for i in range(1, 10):
2	print(f'函数内部 i = {i}')
3print(f'函数外部 i = {i}')
4

1.6函数执行过程

调用函数才会执行函数体代码. 不调用则不会执行.
函数体执行结束(或者遇到return语句),则回到函数调用位置,继续往下执行.

1def test():
2	print("执行函数内部代码")
3	print("执行函数内部代码")
4	print("执行函数内部代码")
5print("1111")
6test()
7print("2222")
8test()
9print("3333")
10


1.7链式调用

1# 判定是否是奇数
2def isOdd(num):
3	if num % 2 == 0:
4		return False
5	else:
6		return True
7result = isOdd(10)
8print(result)
9

实际上也可以简化写作

1print(isOdd(10))
2

把一个函数的返回值, 作为另一个函数的参数, 这种操作称为 链式调用.


1.8嵌套调用

函数内部还可以调用其他的函数, 这个动作称为 “嵌套调用” .

1def test():
2	print("执行函数内部代码")
3	print("执行函数内部代码")
4	print("执行函数内部代码")
5

test 函数内部调用了print函数,这里就属于嵌套调用.

==一个函数里面可以嵌套调用任意多个函数. ==
函数嵌套的过程是非常灵活的.

1def a():
2	print("函数 a")
3def b():
4	print("函数 b")
5	a()
6def c():
7	print("函数 c")
8	b()
9def d():
10	print("函数 d")
11	c()
12d()
13


如果把代码稍微调整, 打印结果则可能发生很大变化.

1def a():
2	print("函数 a")
3def b():
4	a()
5	print("函数 b")
6def c():
7	b()
8	print("函数 c")
9def d():
10	c()
11	print("函数 d")
12d()
13


函数之间的调用关系,在Python中会使用一个特定的数据结构来表示,称为函数调用栈.每次函数调用,都会在调用栈里新增一个元素,称为 栈帧.

每个函数的局部变量,都包含在自己的栈帧中

1def a():
2	num1 = 10
3	print("函数 a")
4def b():
5	num2 = 20
6	a()
7	print("函数 b")
8def c():
9	num3 = 30
10	b()
11	print("函数 c")
12def d():
13	num4 = 40
14	c()
15	print("函数 d")
16d()
17

1.9函数递归

递归是嵌套调用中的一种特殊情况,即一个函数嵌套调用自己.
代码示例: 递归计算 5!

1def factor(n):
2	if n == 1:
3		return 1
4	return n * factor(n - 1)
5result = factor(5)
6print(result)
7

上述代码中,就属于典型的递归操作.在 factor函数内部,又调用了factor自身.
注意: 递归代码务必要保证

  • 存在递归结束条件. 比如 if n == 1 就是结束条件. 当 n 为 1 的时候, 递归就结束了.
  • 每次递归的时候, 要保证函数的实参是逐渐逼近结束条件的.

如果上述条件不能满足, 就会出现 “无限递归” . 这是一种典型的代码错误.

1def factor(n):
2	return n * factor(n - 1)
3result = factor(5)
4print(result)
5


如前面所描述,函数调用时会在函数调用栈中记录每一层函数调用的信息.
但是函数调用栈的空间不是无限大的.如果调用层数太多,就会超出栈的最大范围,导致出现问题.

递归的优点

  • 递归类似于 “数学归纳法” ,明确初始条件,和递推公式,就可以解决一系列的问题.
  • 递归代码往往代码量非常少.

递归的缺点

  • 递归代码往往难以理解, 很容易超出掌控范围
  • 递归代码容易出现栈溢出的情况
  • 递归代码往往可以转换成等价的循环代码.并且通常来说循环版本的代码执行效率要略高于递归版本.

1.10参数默认值

Python 中的函数, 可以给形参指定默认值.
带有默认值的参数, 可以在调用的时候不传参.
代码示例: 计算两个数字的和

1def add(x, y, debug=False):
2	if debug:
3		print(f'调试信息: x={x}, y={y}')
4	return x + y
5print(add(10, 20))
6print(add(10, 20, True))
7

此处debug=False 即为参数默认值.当我们不指定第三个参数的时候, 默认 debug 的取值即为 False. 带有默认值的参数需要放到没有默认值的参数的后面.

1def add(x, debug=False, y):
2	if debug:
3		print(f'调试信息: x={x}, y={y}')
4	return x + y
5print(add(10, 20))
6


1.11关键字参数

在调用函数的时候,需要给函数指定实参.一般默认情况下是按照形参的顺序,来依次传递实参的.但是我们也可以通过 关键字参数,来调整这里的传参顺序,显式指定当前实参传递给哪个形参.

1def test(x, y):
2	print(f'x = {x}')
3	print(f'y = {y}')
4test(x=10, y=20)
5test(y=100, x=200)
6


形如上述 test(x=10, y=20) 这样的操作,即为关键字参数.


2.列表和元组

2.1列表是什么,元组是什么

列表和元组都可以用来保存多个数据。核心区别是:
列表 list:可以修改
元组 tuple:创建后不能修改

列表是一种让程序猿在代码中批量表示/保存数据的方式.
元组和列表相比,是非常相似的,只是列表中放哪些元素可以修改调整,元组中放的元素是创建元组的时候就设定好的,不能修改调整.


2.2创建列表

创建列表主要有两种方式. [ ] 表示一个空的列表.

1alist = [ ]
2alist = list()
3print(type(alist))
4

如果需要往里面设置初始值, 可以直接写在 [ ] 当中.
可以直接使用 print 来打印 list 中的元素内容.

1alist = [1, 2, 3, 4]
2print(alist)
3

列表中存放的元素允许是不同的类型. (这一点和 C++ Java 差别较大).

1alist = [1, 'hello', True]
2print(alist)
3

因为 list 本身是 Python 中的内建函数, 不宜再使用 list 作为变量名, 因此命名为 alist


2.3访问下标

可以通过下标访问操作符 [ ] 来获取到列表中的任意元素.
我们把 [ ] 中填写的数字, 称为 下标 或者 索引 .

1alist = [1, 2, 3, 4]
2print(alist[2])
3

注意: 下标是从0开始计数的,因此下标为2,则对应着3这个元素.
通过下标不光能读取元素内容,还能修改元素的值.

1alist = [1, 2, 3, 4]
2alist[2] = 100
3print(alist)
4

如果下标超出列表的有效范围, 会抛出异常.

1alist = [1, 2, 3, 4]
2print(alist[100])
3


因为下标是从0开始的, 因此下标的有效范围是 [0, 列表长度 - 1]. 使用 len 函数可以获取到列表的元素个数.

1alist = [1, 2, 3, 4]
2print(len(alist))
3

下标可以取负数. 表示"倒数第几个元素"

1alist = [1, 2, 3, 4]
2print(alist[3])
3print(alist[-1])
4

alist[-1] 相当于 alist[len(alist) - 1]


2.4切片操作

通过下标操作是一次取出里面第一个元素.
通过切片, 则是一次取出一组连续的元素, 相当于得到一个 子列表
使用 [ : ] 的方式进行切片操作.

1alist = [1, 2, 3, 4]
2print(alist[1:3])
3


切片操作中可以省略前后边界

1alist = [1, 2, 3, 4]
2print(alist[1:]) # 省略后边界, 表示获取到列表末尾
3print(alist[:-1]) # 省略前边界, 表示从列表开头获取
4print(alist[:]) # 省略两个边界, 表示获取到整个列表.
5


切片操作还可以指定"步长",也就是"每访问一个元素后,下标自增几步"

1alist = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
2print(alist[::1])
3print(alist[::2])
4print(alist[::3])
5print(alist[::5])
6


切片操作指定的步长还可以是负数, 此时是从后往前进行取元素. 表示 “每访问一个元素之后, 下标自减几步”

1alist = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
2print(alist[::-1])
3print(alist[::-2])
4print(alist[::-3])
5print(alist[::-5])
6


如果切片中填写的数字越界了, 不会有负面效果. 只会尽可能的把满足条件的元素过去到.

1alist = [1, 2, 3, 4]
2print(alist[100:200])
3


2.5遍历列表元素

“遍历” 指的是把元素一个一个的取出来, 再分别进行处理.
最简单的办法就是使用 for 循环

1alist = [1, 2, 3, 4]
2for elem in alist:
3	print(elem)
4

也可以使用 for 按照范围生成下标, 按下标访问

1alist = [1, 2, 3, 4]
2for i in range(0, len(alist)):
3	print(alist[i])
4

还可以使用while循环.手动控制下标的变化

1alist = [1, 2, 3, 4]
2i = 0
3while i < len(alist):
4	print(alist[i])
5	i += 1
6

2.6新增元素

使用 append 方法, 向列表末尾插入一个元素(尾插).

1alist = [1, 2, 3, 4]
2alist.append('hello')
3print(alist)
4


使用 insert 方法, 向任意位置插入一个元素

1alist = [1, 2, 3, 4]
2alist.insert(1, 'hello')
3print(alist)
4


2.7查找元素

使用 in 操作符, 判定元素是否在列表中存在. 返回值是布尔类型.

1alist = [1, 2, 3, 4]
2print(2 in alist)
3print(10 in alist)
4


使用index方法,查找元素在列表中的下标.返回值是一个整数.如果元素不存在,则会抛出异常.

1alist = [1, 2, 3, 4]
2print(alist.index(2))
3print(alist.index(10))
4

2.8删除元素

使用 pop 方法删除最末尾元素

1alist = [1, 2, 3, 4]
2alist.pop()
3print(alist)
4


pop 也能按照下标来删除元素

1alist = [1, 2, 3, 4]
2alist.pop(2)
3print(alist)
4


使用 remove 方法, 按照值删除元素.

1alist = [1, 2, 3, 4]
2alist.remove(2)
3print(alist)
4


2.9连接列表

使用 + 能够把两个列表拼接在一起.

1alist = [1, 2, 3, 4]
2blist = [5, 6, 7]
3print(alist + blist)
4


使用extend方法,相当于把一个列表拼接到另一个列表的后面.

1alist = [1, 2, 3, 4]
2blist = [5, 6, 7]
3alist.extend(blist)
4print(alist)
5print(blist)
6


2.10关于元组

元组的功能和列表相比, 基本是一致的.
元组使用 ( ) 来表示.

1atuple = ( )
2atuple = tuple()
3

元组不能修改里面的元素, 列表则可以修改里面的元素
另外, 元组在 Python 中很多时候是默认的集合类型. 例如, 当一个函数返回多个值的时候.

1def getPoint():
2	return 10, 20
3result = getPoint()
4print(type(result))
5


此处的 result 的类型, 其实是元组.
问题来了, 既然已经有了列表, 为啥还需要有元组?
元组相比于列表来说, 优势有两方面:
你有一个列表, 现在需要调用一个函数进行一些处理.但是你有不是特别确认这个函数是否会
把你的列表数据弄乱. 那么这时候传一个元组就安全很多.我们下面要讲的字典,是一个键值对结构. 要求字典的键必须是 “可hash对象” (字典本质上也是一个hash表). 而一个可hash对象的前提就是不可变. 因此元组可以作为字典的键, 但是列表不行.


3.字典

3.1字典是什么

字典是一种存储 键值对 的结构.
啥是键值对? 这是计算机/生活中一个非常广泛使用的概念.
把 键(key) 和 值(value) 进行一个一对一的映射, 然后就可以根据键, 快速找到值.
可以理解为现实中的通讯录:
姓名是“键”
电话号码是“值”


3.2创建字典

创建一个空的字典. 使用 { } 表示字典.

1a = { }
2b = dict()
3print(type(a))
4print(type(b))
5

也可以在创建的同时指定初始值
键值对之间使用 , 分割, 键和值之间使用 : 分割. (冒号后面推荐加一个空格).
使用 print 来打印字典内容

1student = { 'id': 1, 'name': 'zhangsan' }
2print(student)
3

为了代码更规范美观, 在创建字典的时候往往会把多个键值对, 分成多行来书写.

1student = {
2'id': 1,
3'name': 'zhangsan'
4}
5

最后一个键值对,后面可以写,也可以不写.

1student = {
2'id': 1,
3'name': 'zhangsan',
4}
5

3.3查找 key

使用in可以判定key是否在字典中存在.返回布尔值.

1student = {
2'id': 1,
3'name': 'zhangsan',
4}
5print('id' in student)
6print('score' in student)
7

使用 [ ] 通过类似于取下标的方式, 获取到元素的值. 只不过此处的"下标"是 key. (可能是整数, 也可能是字符串等其他类型).

1student = {
2'id': 1,
3'name': 'zhangsan',
4}
5print(student['id'])
6print(student['name'])
7

如果 key 在字典中不存在, 则会抛出异常.

1student = {
2'id': 1,
3'name': 'zhangsan',
4}
5print(student['score'])
6

3.4新增/修改元素

使用 [ ] 可以根据 key 来新增/修改 value.
如果 key 不存在, 对取下标操作赋值, 即为新增键值对

1student = {
2'id': 1,
3'name': 'zhangsan',
4}
5student['score'] = 90
6print(student)
7

如果 key 已经存在, 对取下标操作赋值, 即为修改键值对的值.

1student = {
2'id': 1,
3'name': 'zhangsan',
4'score': 80
5}
6student['score'] = 90
7print(student)
8

3.5删除元素

使用 pop 方法根据 key 删除对应的键值对.

1student = {
2'id': 1,
3'name': 'zhangsan',
4'score': 80
5}
6student.pop('score')
7print(student)
8

3.6遍历字典元素

直接使用 for 循环能够获取到字典中的所有的 key, 进一步的就可以取出每个值了.

1student = {
2'id': 1,
3'name': 'zhangsan',
4'score': 80
5}
6for key in student:
7print(key, student[key])
8

3.7取出所有 key 和 value

使用 keys 方法可以获取到字典中的所有的 key

1student = {
2'id': 1,
3'name': 'zhangsan',
4'score': 80
5}
6print(student.keys())
7

此处 dict_keys 是一个特殊的类型, 专门用来表示字典的所有 key. 大部分元组支持的操作对于
dict_keys 同样适用.使用 values 方法可以获取到字典中的所有 value

1student = {
2'id': 1,
3'name': 'zhangsan',
4'score': 80
5}
6print(student.values())
7

此处 dict_values 也是一个特殊的类型, 和 dict_keys 类似.使用 items 方法可以获取到字典中所有的键值对.

1student = {
2'id': 1,
3'name': 'zhangsan',
4'score': 80
5}
6print(student.items())
7

3.8合法的 key 类型

不是所有的类型都可以作为字典的 key.
字典本质上是一个 哈希表, 哈希表的 key 要求是 “可哈希的”, 也就是可以计算出一个哈希值.
可以使用 hash 函数计算某个对象的哈希值.
但凡能够计算出哈希值的类型, 都可以作为字典的 key.

1print(hash(0))
2print(hash(3.14))
3print(hash('hello'))
4print(hash(True))
5print(hash(())) # ( ) 是一个空的元组
6

列表无法计算哈希值.

1print(hash([1, 2, 3]))
2

字典也无法计算哈希值

1print(hash({ 'id': 1 }))
2

4.文件

4.1文件是什么

变量是把数据保存到内存中. 如果程序重启/主机重启, 内存中的数据就会丢失.
要想能让数据被持久化存储, 就可以把数据存储到硬盘中. 也就是在 文件 中保存.
在 Windows “此电脑” 中,看到的内容都是文件.
通过文件的后缀名, 可以看到文件的类型. 常见的文件的类型如下:
文本文件 (txt)
可执行文件 (exe, dll)
图片文件 (jpg, gif)
视频文件 (mp4, mov)
office 文件 (.ppt, docx)


4.2文件路径

一个机器上, 会存在很多文件, 为了让这些文件更方面的被组织, 往往会使用很多的 “文件夹”(也叫做目录)来整理文件.实际一个文件往往是放在一系列的目录结构之中的. 为了方便确定一个文件所在的位置, 使用 文件路径 来进行描述. 目录之间的分隔符, 可以使用 \ 也可以使用 / . 一般在编写代码的时候使用 / 更方便. 上述以盘符开头的路径, 我们也称为 绝对路径.除了绝对路径之外,还有一种常见的表示方式是相对路径.相对路径需要先指定一个基准目录,然后以基准目录为参照点, 间接的找到目标文件.描述一个文件的位置,使用绝对路径和相对路径都是可以的.对于新手来说,使用绝对路径更简单更好理解,也不容易出错.


4.3文件操作

要使用文件, 主要是通过文件来保存数据, 并且在后续把保存的数据读取出来.
但是要想读写文件, 需要先 “打开文件”, 读写完毕之后还要 “关闭文件”.


4.3.1打开文件

使用内建函数 open 打开一个文件.

1f = open('d:/test.txt', 'r')
2

第一个参数是一个字符串, 表示要打开的文件路径
第二个参数是一个字符串, 表示打开方式. 其中 r 表示按照读方式打开. w 表示按照写方式打开. a表示追加写方式打开.
如果打开文件成功, 返回一个文件对象. 后续的读写文件操作都是围绕这个文件对象展开.
如果打开文件失败(比如路径指定的文件不存在), 就会抛出异常.


4.3.2关闭文件

使用 close 方法关闭已经打开的文件.

1f.close()
2

使用完毕的文件要记得及时关闭!
一个程序能同时打开的文件个数, 是存在上限的.

1flist = []
2count = 0
3while True:
4	f = open('d:/test.txt', 'r')
5	flist.append(f)
6	count += 1
7	print(f'count = {count}')
8

4.3.3写文件

文件打开之后, 就可以写文件了.
写文件, 要使用写方式打开, open 第二个参数设为 ‘w’
使用 write 方法写入文件.

1f = open('d:/test.txt', 'w')
2f.write('hello')
3f.close()
4

如果是使用 ‘r’ 方式打开文件, 则写入时会抛出异常.

1f = open('d:/test.txt', 'r')
2f.write('hello')
3f.close()
4

使用 ‘w’ 一旦打开文件成功, 就会清空文件原有的数据.
使用 ‘a’ 实现 “追加写”, 此时原有内容不变, 写入的内容会存在于之前文件内容的末尾.

1f = open('d:/test.txt', 'w')
2f.write('hello')
3f.close()
4f = open('d:/test.txt', 'a')
5f.write('world')
6f.close()
7

针对已经关闭的文件对象进行写操作, 也会抛出异常.

1f = open('d:/test.txt', 'w')
2f.write('hello')
3f.close()
4f.write('world')
5

4.3.4读文件

读文件内容需要使用 ‘r’ 的方式打开文件
使用 read 方法完成读操作. 参数表示 “读取几个字符”

1f = open('d:/test.txt', 'r')
2result = f.read(2)
3print(result)
4f.close()
5

如果文件是多行文本, 可以使用 for 循环一次读取一行.

1f = open('d:/test.txt', 'r')
2for line in f:
3	print(f'line = {line}')
4f.close()
5

使用 readlines 直接把文件整个内容读取出来, 返回一个列表. 每个元素即为一行.

1f = open('d:/test.txt', 'r')
2lines = f.readlines()
3print(lines)
4f.close()
5

4.4关于中文的处理

当文件内容存在中文的时候, 读取文件内容不一定就顺利.
计算机表示中文的时候, 会采取一定的编码方式, 我们称为 “字符集”
所谓 “编码方式” , 本质上就是使用数字表示汉字.我们知道,计算机只能表示二进制数据.要想表示英文字母, 或者汉字, 或者其他文字符号, 就都要通过编码.最简单的字符编码就是ascii.使用一个简单的整数就可以表示英文字母和阿拉伯数字.但是要想表示汉字,就需要一个更大的码表.
一般常用的汉字编码方式,主要是 GBK 和 UTF-8必须要保证文件本身的编码方式,和 Python 代码中读取文件使用的编码方式匹配,才能避免出现上述问题.Python3 中默认打开文件的字符集跟随系统, 而简体中文版的字符集采用了 GBK, 所以如果文件本身是 GBK 的编码, 直接就能正确处理. 如果文件本身是其他编码(比如 UTF-8), 那么直接打开就可能出现上述问题.
如果此处的编码为ANSI,则表示 GBK 编码. 如果此处为UTF-8,则表示UTF-8编码.此时修改打开文件的代码,给 open 方法加上 encoding 参数, 显式的指定为和文本相同的字符集, 问题
即可解决.

1f = open('d:/test.txt', 'r', encoding='utf8')
2

4.5使用上下文管理器

打开文件之后, 是容易忘记关闭的. Python 提供了 上下文管理器 , 来帮助程序猿自动关闭文件.
使用 with 语句打开文件.
当 with 内部的代码块执行完毕后, 就会自动调用关闭方法.

1with open('d:/test.txt', 'r', encoding='utf8') as f:
2lines = f.readlines()
3print(lines)
4

🚀真正的勇者不是流泪的人,而是含泪奔跑的人!


敬请期待下一篇文章内容


每日心灵鸡汤: 真正拉开差距的,是一个人的底层决策逻辑!

一个人开始变富,往往不是因为赚到了钱,而是因为底层决策逻辑发生了改变:他开始把时间视为最稀缺的资产,拒绝无效消耗;不再向外证明自己,而是向内积累资产;学习不再为了竞争,而是为了理解世界运行的规律;接受长期主义,能够忍受延迟回报;收入增长后,不升级欲望,而是升级资本积累能力.真正拉开人与人差距的,从来不是收入,而是一个人如何看待时间、认知、欲望和未来.


【Python学习】(认识函数、列表、元组、字典与文件核心知识要点)》 是转载文章,点击查看原文


相关推荐


Java ActiveMQ 实战指南:从 JMS 队列、主题到 Spring Boot 消息处理
唐青枫2026/7/8

简介 ActiveMQ 是 Apache 提供的消息中间件。 它在 Java 生态里很常见,尤其是传统企业系统、老项目改造、JMS 规范相关系统中出现得比较多。 简单理解: 生产者 | v ActiveMQ Broker | v 消费者 ActiveMQ 最常见的使用方式是 JMS。 JMS 全称是 Java Message Service,它是一套 Java 消息服务 API 规范。 ActiveMQ 和 JMS 的关系可以类比成: JMS 是规范 ActiveMQ 是实现


SPI 加入 Apple,Swift 迈向自举 -- 肘子的 Swift 周报 #142
东坡肘子2026/6/30

SPI 加入 Apple,Swift 迈向自举 几天前,Swift Package Index(SPI)宣布已加入 Apple。双方将共同建设一个面向 Swift 开发者的综合 package registry;与此同时,SPI 现有的包发现、兼容性检查、文档托管等能力仍会继续提供,包作者在短期内也无需调整现有的发布流程。 这也让 #135⁠ 中“SwiftPM 才刚到第二章”的判断得到了新的注脚:CocoaPods 的退场只是把 SPM 推上了默认位置,而 SPI 加入 Apple,才真正揭开


@开发者,提前解锁 FORCE 原动力大会五大看点,限时赢取门票福利
火山引擎Agent社区2026/6/21

过去一年,AI 关注点不断变化,从大模型能力,进一步包括 Agent 能力。能力重点从“生成内容”转向“执行任务”,应用形态也从单点交互,走向多 Agent 协同和系统级运行。 对开发者来说,问题也变了:不只是模型选型,Agent 怎么设计、怎么跑稳、怎么进入真实业务系统,同样成为必须面对的课题。 围绕这些关键问题,我们梳理出 FORCE 原动力大会值得开发者关注的五大亮点。 Future|论坛前沿议题 获得 Agent 时代的技术坐标 Agent 的下一阶段竞争,不只是模型能力,更是系统能


初始化微信小程序
Oneslide2026/6/13

安装miniprogram-cli F:\business-system\weixin-app-order>npm install -g @wechat-miniprogram/miniprogram-cli npm warn deprecated inflight@1.0.6: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tes


我做了一面互联网摸鱼墙:从无限 Canvas 到本地生产环境
戈德斯文2026/6/6

最近,我做了一个叫「摸鱼表格」的小项目。 它看起来像表格,却没有表头、公式、筛选和工作任务。这里有的,只是一面可以无限拖动、缩放和探索的公共格子墙。 任何人都能选一个空格,写下一句话、一个突然冒出的想法,或者把它当成临时树洞。 项目已经可以直接体验: moyu-table.tangyuan.art 这篇文章不只展示成品。我想完整复盘一次:一个看似简单的互动想法,如何逐步变成拥有数据库、登录、部署、备份和公网入口的产品。 一、它像表格,但这里没有标准答案 传统表格围绕效率组织信息:表头定义含义


Gateway 鉴权场景:网关统一鉴权 + 业务应用决定放行规则
超梦dasgg2026/5/30

目录 一、核心设计原则(一句话总结) 二、具体实现方案(最主流、最推荐) 1. 整体流程 2. 具体技术实现(Spring Cloud Gateway 为例) (1)业务服务:定义注解 + 扫描接口路由 (2)业务服务:启动时自动上报路由权限规则 (3)Gateway:拉取规则 + 全局过滤器统一鉴权 三、更轻量的简化方案(中小型项目常用) 四、为什么要这么设计?(面试加分回答) 五、面试标准回答(你可以直接背) 总结 这是微服务架构中最标准、最常用的鉴权方案:G


保姆级教程:零成本在本地跑AI大模型_Ollama
凤年徐2026/5/8

保姆级教程:零成本在本地跑 AI 大模型——Ollama 从安装到实战 手把手教你,用自己的电脑跑起来满血版 Qwen/DeepSeek/Llama,不需要 API Key,不需要云服务器 预计完成时间: 2-3 小时 所需技能: 会用命令行(3条命令够了) 适合人群: 想玩 AI 大模型但不想花钱、担心隐私泄露、喜欢折腾的同学 前言:为什么要在本地跑大模型? 用过 ChatGPT、DeepSeek 的同学应该知道,每次调用都是要花钱的——DeepSeek-V3 每次 A


我让 AI 当了回老师,把 Claude Code 从头到尾盘了一遍 🔥
LinDaiDai_霖呆呆2026/4/29

前言 你盼世界,我盼望你无bug。Hello 大家好,我是霖呆呆! 最近尝试在用 Claude Code 写项目,建仓库、修 bug、代码审查什么的都用它。但说实话,用是用了,总感觉自己就是个"面向弹窗编程"选手 —— 它弹窗我就点确认,它问我就说好,至于它到底是怎么运作的?权限模式有几种?Hooks 能干嘛?emmm...😅 直到我发现三元写了个 skill(名为 sigma) ,安装完后在 claudeCode 里使用 /sigma 你想学习的知识 命令,它就能变身 AI 1v1 家教,


拒绝低效!这款神器,让你的终端效率起飞 | 深度解析 fzf 终极指南
GetcharZp2026/4/20

还在手动敲 cd 和 ls?还在繁琐的 history 中翻找命令?是时候换个方式工作了。一篇文章带你彻底掌握命令行模糊找回神器 fzf,从安装到进阶玩法,助你效率翻倍! 身为开发者,我们每天大部分的时间都花在了终端(Terminal)里。不论是切换目录、搜索文件,还是翻阅历史命令,这些细碎的操作如果效率低下,积少成多便会吞噬掉大量专注力。 你是否也曾经历过: 想找一个深层目录下的文件,却记不清完整路径,只能不断 ls 确认? 按 Ctrl+R 搜索历史命令,结果搜出来的不是自己想要的?


OpenClaw实操指南13|用AI接管飞书多维表格:自动建表、写数据、做分析,一条指令搞定
Rubin智造社2026/4/12

飞书多维表格是很多团队的数据中枢——项目管理、内容选题、客户跟进、数据分析,全在里面。 但维护它是个体力活:手动建字段、逐条录数据、定期整理……重复劳动大量消耗精力。 这篇教程教你用OpenClaw的lark全套技能,把飞书多维表格的常见操作全部交给AI。 一条指令建表,一条指令批量写数据,一条指令做分析汇总。你只需要告诉AI你要什么,剩下的它来做。 核心概要 这篇解决什么问题? 安装并配置lark全套技能,实现飞书多维表格的AI自动化操作:建表、字段管理、数据读写、视图

首页编辑器站点地图

本站内容在 CC BY-SA 4.0 协议下发布

Copyright © 2026 聚合阅读