Python基础(二)
Python基础
组合数据类型
在大数据时代,程序往往不仅要处理数字、字符串这类基础数据类型,还需要应对更复杂的混合数据。为此,Python 提供了多种可以容纳不同类型数据的组合数据类型。使用这些数据结构,不仅能让数据组织更清晰,也能极大地简化开发过程,提升效率。
认识组合数据类型
组合数据类型可以将多个相同或不同类型的数据组织为一个整体。按照数据的组织方式,Python 的组合数据类型主要分为三类:序列类型、集合类型、映射类型。
序列类型
Python 中常见的序列类型包括:字符串(str)、列表(list) 和 元组(tuple)。
序列支持 双向索引——
- 从左到右的正向索引:第一个元素索引为 0;
- 从右到左的反向索引:最后一个元素索引为 -1。
集合类型
集合具备 确定性、互异性、无序性 三个特征。
集合中的元素必须是不可变类型,例如整型、浮点型、字符串、元组,而不能是列表或字典。
- 确定性:某个元素是否在集合中是确定的;
- 互异性:集合中元素不会重复;
- 无序性:元素无固定顺序。
映射类型
映射类型以键值对形式存储数据,最典型的就是 字典(dict)。
字典的每个键都对应一个值,键必须是不可变类型,且不能重复。
列表
列表是 Python 中最灵活的序列类型,它使用一段连续的内存空间存储元素,没有长度限制,可包含任意类型数据。开发者可以对列表中的元素进行添加、删除、排序等多种操作。
创建列表
Python 创建列表的方式非常直观:
list_one=['a','b']
list_two=list({'a','b'})
list_tree=list({'name':'jack','age':18})
print(type(list_one),list_one)
print(type(list_two),list_two)
print(type(list_tree),list_tree)
列表中的元素可以是数字、字符串、元组、字典等任意类型。
访问列表元素
可以通过索引或切片访问列表元素,也可以在循环中依次访问。
list_dev=['java','c#','python', 'php']
print(list_dev[2])
print(list_dev[-2])
print(len(list_dev))
print(list_dev[len(list_dev)-1])#输出
python
python
4
php
切片操作用于获取部分元素:
list_char=['a','b','c','d','e','f']
print(list_char[1:-1:1])
print(list_char[1:-1:2])
print(list_char[2:])
print(list_char[:-2])
print(list_char[::2])#输出
['b', 'c', 'd', 'e']
['b', 'd']
['c', 'd', 'e', 'f']
['a', 'b', 'c', 'd']
['a', 'c', 'e']
列表是可迭代对象(数值类型不属于可迭代对象),可以用循环访问:
list_one=['a','b']
from collections.abc import Iterable
print(isinstance(list_one,Iterable))
print(isinstance(range(5),Iterable))
print(isinstance('abc',Iterable))
for i in 'abc':print(i)
print(isinstance(3.14,Iterable))
print(isinstance(True,Iterable))
print(isinstance(3j+10,Iterable))#输出
True
True
True
a
b
c
False
False
False
成员运算符 in 和 not in 可判断元素是否存在于列表中:
print('e'in list_char)
添加列表元素
Python 提供了多种添加元素的方法。
list_one=['a','b','c']
list_two=[10,20,30]
list_one.extend(list_two)
print(list_one)
list_one.extend('python')
print(list_one)
#总结: extend作用: 改变原有列表结构,并把其他类型转换成列表类型#输出
['a', 'b', 'c', 10, 20, 30]
['a', 'b', 'c', 10, 20, 30, 'p', 'y', 't', 'h', 'o', 'n']#指定位置插入
list_one=['a','b','c']
list_one.insert(1,10)
print(list_one)
#输出
['a', 10, 'b', 'c']
列表排序
列表支持升序、降序、反向等多种排序方式。
list_one=[10,35,9,55,40,620,512,78,5962,8841,2185,7213]
list_two=['t','y','f','w','j','i']
list_three=['blue','sky','fix','dog','monkey','body']
list_four=['吃饭','开车','喝水','旅游','玩手机','拉屎','睡觉']
list_five=['fg','afsegrd','hushu','xcvbnm,','qwertyuiop','sdd']
list_one.sort(reverse=True)
print(list_one)
list_two.sort(reverse=True)
print(list_two)
list_three.sort()
print(list_three)
list_four.sort()
print(list_four)
list_five.sort(key=len)
print(list_five)#输出
[8841, 7213, 5962, 2185, 620, 512, 78, 55, 40, 35, 10, 9]
['y', 'w', 't', 'j', 'i', 'f']
['blue', 'body', 'dog', 'fix', 'monkey', 'sky']
['吃饭', '喝水', '开车', '拉屎', '旅游', '玩手机', '睡觉']
['fg', 'sdd', 'hushu', 'afsegrd', 'xcvbnm,', 'qwertyuiop']
sorted() 会返回一个新列表,不修改原列表:
list_one=[10,35,9,55,40,620,512,78,5962,8841,2185,7213]
new_list=sorted(list_one)
print(new_list)
print(list_one)
print(sorted(list_one))#输出
[9, 10, 35, 40, 55, 78, 512, 620, 2185, 5962, 7213, 8841]
[10, 35, 9, 55, 40, 620, 512, 78, 5962, 8841, 2185, 7213]
[9, 10, 35, 40, 55, 78, 512, 620, 2185, 5962, 7213, 8841]
反转列表:
list_four=['吃饭','开车','喝水','旅游','玩手机','拉屎','睡觉']
list_four.reverse()
print(list_four)#输出
['睡觉', '拉屎', '玩手机', '旅游', '喝水', '开车', '吃饭']
删除列表元素
list_four=['吃饭','开车','喝水','旅游','玩手机','拉屎','睡觉']
del list_four[2]
# del list_four
print(list_four)#输出
['吃饭', '开车', '旅游', '玩手机', '拉屎', '睡觉']list_four=['吃饭','开车','喝水','旅游','玩手机','拉屎','睡觉']
list_four.remove('拉屎')
print(list_four)#输出
['吃饭', '开车', '喝水', '旅游', '玩手机', '睡觉']# pop删除元素并且返回该元素
list_seven=['张三','李四','王五','赵六','孙七']
result=list_seven.pop(0)
print(list_seven)
print('返回值: ',result)#输出
['李四', '王五', '赵六', '孙七']
返回值: 张三
列表推导式
列表推导式可用简洁的语法生成新列表:
#原始
num_list=[1,2,3,4,5,6,7,8,9]
new_list=[]
for tmp in num_list:new_list.append(tmp**2)
print(new_list)#输出
[1, 4, 9, 16, 25, 36, 49, 64, 81]#推导式
num_list=[1,2,3,4,5,6,7,8,9]
print([tmp**2 for tmp in num_list])#输出
[1, 4, 9, 16, 25, 36, 49, 64, 81]
嵌套循环:
#原始
num_list=[1,2,3,4,5,6,7,8,9]
new_list=[]
for tmp in num_list:if tmp%2!=0:new_list.append(tmp**2)
print(new_list)#输出
[1, 9, 25, 49, 81]#推导式
num_list=[1,2,3,4,5,6,7,8,9]
print([tmp**2 for tmp in num_list if tmp%2!=0])#输出
[1, 9, 25, 49, 81]
总结
- 列表创建:
- 可直接用
[]定义,也可通过list()函数将集合、字典(默认取键)等可迭代对象转换为列表。
- 可直接用
- 可迭代对象:
- 列表、range 对象、字符串等属于可迭代对象,可通过
isinstance()结合Iterable判断;数值类型(int、float、complex)及布尔值不属于可迭代对象。
- 列表、range 对象、字符串等属于可迭代对象,可通过
- 列表查看与访问:
- 支持索引(正索引、负索引)、切片(指定起始、结束、步长)访问元素;
- 可通过
len()获取长度,用in判断元素是否存在。
- 列表元素添加与扩展:
append()用于末尾追加元素;extend()可将其他可迭代对象的元素添加到列表,改变原列表;insert()在指定位置插入元素。
- 列表排序与逆置:
sort()对原列表排序(支持reverse参数控制升降序,key指定排序依据如长度);reverse()将原列表元素逆置;sorted()排序后生成新列表,不改变原列表。
- 列表元素删除:
del通过索引删除元素或删除整个列表;remove()删除指定元素(需存在,可通过循环删除所有相同元素);pop()删除指定索引元素并返回该元素,默认删除最后一个。
- 列表推导式:
- 简化列表生成,如
[tmp**2 for tmp in num_list]生成平方列表,可结合条件筛选(如只计算奇数平方:[tmp**2 for tmp in num_list if tmp%2!=0])。
- 简化列表生成,如
整体展现了列表作为可变序列的灵活性,支持动态增删改查及高效的元素处理方式。
元组
元组使用圆括号 () 包裹,元素之间用逗号分隔。
它与列表类似,但不可修改(即元素不能增删改)。
#空元组
tuple_one=('hello')
print(type(tuple_one))
tuple_two=tuple('hello')
tuple_two=tuple(range(5))
tuple_two=tuple({'name':'jack','age':23})
print(type(tuple_two))
print(tuple_two)#输出
<class 'str'>
<class 'tuple'>
('name', 'age')tuple_one=('hello','world',10,20,30)
tuple_two=[100,200,300]
print(tuple_one[0])
print(tuple_one[1:3:1])
print(tuple_one+tuple_two)#输出
hello
('world', 10)
TypeError: can only concatenate tuple (not "list") to tuple#总结:
#和列表的相同点:序列,可以查看(索引,切片,遍历),同类型拼接,都可以使用de1删除
#和列表的不同点:不可以(增,删除元素,修改),一个元素的存在方式
#作用场景:高安全场合,数据安全,读取速度快。info=[]
for i in range(10):grade=input('请输入成绩:')info.append(grade)print(info)
info.remove(max(info))
info.remove(min(info))
pj=sum(info)/len(info)
print(pj)info = []
for i in range(10):grade = float(input('请输入成绩:'))info.append(grade)print(info)
info.remove(max(info))
info.remove(min(info))
pj = sum(info) / len(info)
print(f"最终平均分:{pj:.2f}")
总结
- 元组相关:
- 创建与类型:单元素元组需注意
('hello')实际为字符串类型,tuple()函数可通过字符串、range 对象、字典(默认取键)等创建元组,元组类型为tuple。 - 操作特性:作为序列,元组支持索引访问、切片、与列表等序列类型拼接;与列表的区别在于元组不可增删改元素,单元素元组需特殊处理(如
('hello',))。 - 应用场景:适用于高安全性场合,数据不可修改,且读取速度较快。
- 创建与类型:单元素元组需注意
- 成绩处理代码:
- 功能:通过循环输入 10 个成绩并存储到列表,移除最高分和最低分后计算并输出平均分。
- 修正:需将输入的成绩转换为浮点型(
float),否则无法正确进行max、min、sum等数值操作,最终可格式化输出保留两位小数的平均分。
整体展现了元组的不可变特性及列表在动态数据处理中的应用。
集合
集合的核心特性是:
- 无序性(无固定顺序,不可索引)
- 唯一性(自动去重)
- 不可变性(元素必须是不可变类型,如数字、字符串、元组等)
因此,不能像列表、字符串那样用索引访问集合元素。
集合使用大括号 {} 表示,具有无序且唯一的特性。
s1 = {1, 'b', (2,5)}
s2 = set()
s3 = set([1,2,3])
s4 = set('python')
print(s3) # {1, 2, 3}
print(s4) # {'h', 'p', 'n', 'o', 'y', 't'}
集合操作示例:
#创建集合
set_one={2}
print(type(set_one))
set_two=set([10,20,30,20,11,33,30])
print(set_two)
set_two=set('tools')
print(set_two)
set_two=set([10,20,30,40,50,60,70,80])
print(set_two)
print(set_two[0])#输出
<class 'set'>
{33, 10, 11, 20, 30}
{'t', 'l', 's', 'o'}
{70, 40, 10, 80, 50, 20, 60, 30}
Traceback (most recent call last):File "E:\pyhtonurl\.venv\105\组合数据类型\集合.py", line 10, in <module>print(set_two[0])~~~~~~~^^^
TypeError: 'set' object is not subscriptable#添加
set_two=set([10,20,30,40,50,60,70,80])
# set_two.add(90)
result=set_two.add(90)
# print(set_two)
print(result)#输出
None#删除
set_two=set([10,20,30,40,50,60,70,80])
# set_two.remove(80)
# set_two.remove(90)
set_two.discard(90)
set_two.pop()
print(set_two)
result=set_two.pop()
print(result)#输出
{40, 10, 80, 50, 20, 60, 30}
40#discard(x):安全移除元素,不存在则无操作。
#pop():随机移除元素并返回,集合为空时调用会报错(KeyError)。
#remove 如果元素不存在则抛出异常,discard,如果元素不存在则不抛出异常
#pop 随机删除,如果集合为空则抛出异常#清空
set_two.clear()#复制
set_two=set([10,20,30,40,50,60,70,80])
new_set=set_two.copy()
print(new_set)print(set_two)
new_set.discard(50)
print(new_set)#输出
{70, 40, 10, 80, 50, 20, 60, 30}
{70, 40, 10, 80, 50, 20, 60, 30}
{70, 40, 10, 80, 20, 60, 30}#检查集合相同元素
set_one={11,22,33,44,55,66,77,88}
set_two=set([10,20,30,40,50,60,70,80])
print(set_one.isdisjoint((set_two)))
set_one={11,22,33,44,55,66,77,88}
set_two=set([10,20,30,40,50,60,70,80,88])
print(set_one.isdisjoint((set_two)))#输出
True
False
总结
- 集合创建:
- 可用
{元素}创建(单元素需注意与字典区分); - 可通过
set()函数,传入列表、字符串等可迭代对象创建,且集合会自动去重; - 集合是无序的,不能通过索引访问元素(如
set_two[0]会报错)。
- 可用
- 元素添加:
- 用
add()方法添加元素,该方法无返回值(返回None)。
- 用
- 元素删除:
remove(元素):删除指定元素,元素不存在则抛出异常;discard(元素):删除指定元素,元素不存在也不抛出异常;pop():随机删除一个元素并返回该元素,若集合为空则抛出异常。
- 其他操作:
clear():清空集合;copy():复制集合,生成新集合,修改新集合不影响原集合。
- 集合关系判断:
isdisjoint(另一集合):判断两个集合是否没有相同元素,无相同元素返回True,有则返回False。
整体体现了集合无序、去重的特性,以及其常用的创建、增删、复制和关系判断等操作。
字典
遍历
dict_two=dict(ll=00)
dict_two=dict(ll=[70,80,90],name='jack',age=18)
print(dict_two)
# 遍历所有键值对
for k,v in dict_two.items():print(k,v)#输出
{'ll': [70, 80, 90], 'name': 'jack', 'age': 18}
ll [70, 80, 90]
name jack
age 18
字典使用 {键:值} 的形式存储数据,每个键对应一个值。
d = {'A':'123', 'B':'135', 'C':'680'}
print(d['A']) # 123
print(d.get('B')) # 135
添加或修改元素:
#字典元素添加
dict_one={'name':'jack','age':18}
dict_one['address']='nanjing'
print(dict_one)
dict_one.update(address='nanjing')
print(dict_one)#输出
{'name': 'jack', 'age': 18, 'address': 'nanjing'}
{'name': 'jack', 'age': 18, 'address': 'nanjing'}#字典元素修改
dict_one={'name':'jack','age':18}
dict_one['age']=20
print(dict_one)
dict_one.update(age=20)
print(dict_one)#输出
{'name': 'jack', 'age': 20}
{'name': 'jack', 'age': 20}
删除元素:
dict_one={'name':'jack','age':18}
dict_one.pop('name')
print(dict_one)
dict_one.popitem()
print(dict_one)#输出
{'age': 18}
{}
总结
- 字典定义:有两种方式,一是使用空大括号
{},二是通过dict()函数,两者都能创建空字典。 - 字典初始化:既可以直接在大括号中写入键值对,也可以通过
dict()函数传入参数的方式初始化,键值对中值的类型可以多样(如列表、字符串、数字等)。 - 元素查看:可通过键直接访问(
字典名['键']),也可使用get('键')方法获取对应值。 - 遍历操作:能遍历所有键值对(
items())、仅遍历键(keys())或仅遍历值(values())。 - 元素添加:可通过新键赋值的方式,也可使用
update()方法添加新的键值对。 - 元素修改:通过键重新赋值或
update()方法对已有键的值进行修改。 - 元素删除:
pop('键')删除指定键的元素,popitem()删除最后一个键值对,clear()清空字典(无返回值)。
函数
在实际开发中,如果有多段执行逻辑完全相同的代码,就可以将它们抽取出来封装成函数。这样既能提高代码复用率,又能让程序结构更清晰、可维护性更强。
函数概述
函数是一段组织良好、实现特定功能的代码块。
在 Python 中,可以把函数看作是一段“可重复使用的、有名字的代码”,在需要时用 函数名() 调用即可。
str_one = 'hello'
str_two = 'world'
print(str_one + str_two)list_one = [1, 2, 3]
list_two = [4, 5, 6]
print(list_one + list_two)tuple_one = (10, 20, 30)
tuple_two = (40, 50, 60)
print(tuple_one + tuple_two)
运行结果:
helloworld
[1, 2, 3, 4, 5, 6]
(10, 20, 30, 40, 50, 60)
再看一个例子,假设我们要打印不同边长的正方形。
未使用函数前:
for i in range(2):for j in range(2):print('*', end=' ')print()for i in range(3):for j in range(3):print('*', end=' ')print()for i in range(4):for j in range(4):print('*', end=' ')print()
代码重复,修改不便。
使用函数后:
def print_square(length):for i in range(length):for j in range(length):print('*', end=' ')print()print_square(2)
print_square(3)
print_square(4)
简洁清晰,可随时重复调用。
使用函数的优点:
- 程序模块化,减少冗余;
- 提高开发效率;
- 方便维护与扩展。
函数的定义与调用
Python 定义函数的格式非常简洁:
def 函数名(参数列表):函数体
例如:
#无参函数定义
def add():result=11+22print(result)
#调用
add()#输出
33#带参函数定义
def func_add(a,b):result=a+bprint(result)
#调用
func_add(5,4)#输出
9
运行流程如下:
- 程序执行到函数调用位置时暂停;
- 将数据传递给函数;
- 执行函数体;
- 执行完毕后返回原位置继续运行。
嵌套调用与嵌套定义
函数中可以调用其他函数,这叫嵌套调用:
def add():result=11+22print(result)
def func_add(a,b):result=a+badd() #嵌套调用print(result)
func_add(4,8)#输出
33
12
函数也可以在内部定义另一个函数,这叫嵌套定义:
def outer():def inner():print("内层函数")inner()outer()
注意:
- 内层函数不能在外部直接调用;
- 必须通过外层函数间接调用。
函数参数传递
定义函数时设置的参数称为形参;
调用函数时传入的参数称为实参。
Python 支持多种参数传递方式:位置参数、关键字参数、默认参数、打包与解包、混合传递。
位置参数
实参按照定义顺序依次传给形参:
def get_max(a, b):if a > b:print('max:', a)else:print('max:', b)get_max(5, 8)
关键字参数
通过“形参名=实参值”的形式传递:
def func(ip,port):print(f'主机地址是: {ip},端口是:{port}')
func(port=8080,ip='192.168.10.1')
输出:
主机地址是: 192.168.10.1,端口是:8080
默认参数
定义函数时可为形参设置默认值:
def func(ip,port=8080):print(f'主机地址是: {ip},端口是:{port}')
func(ip='192.168.50.2')
func(ip='192.168.50.2',port=3306)
输出:
主机地址是: 192.168.50.2,端口是:8080
主机地址是: 192.168.50.2,端口是:3306
参数的打包与解包
当参数数量不确定时,可以使用 * 或 **:
#参数符号 / *
def func(a,/,b,*,c):print(a,b,c)
#/的左边只能使用位置传参,*的右边只能使用关键字传参
func(10,20,c=30)
def func(*args):for i in args:print(i)
func(1,2,3,4,5,6,7,8,9)def func(**kwargs):for k,v in kwargs.items():print(k,v)
func(name='666',age=512,score=[11,22,33],address='nanjing')#输出
1
2
3
4
5
6
7
8
9
name 666
age 512
score [11, 22, 33]
address nanjing
解包:
num_tuple=(10,20,30,40)
info_dict={'a':10,'b':20,'c':30,'d':40}
混合参数传递
定义函数时参数的顺序要遵守规则:
- 普通参数 → 默认参数 →
*args→**kwargs
示例:
def test(a, b, c=33, *args, **kwargs):print(a, b, c, args, kwargs)test(1, 2)
test(1, 2, 3)
test(1, 2, 3, 4)
test(1, 2, 3, 4, e=5)
输出:
1 2 33 () {}
1 2 3 () {}
1 2 3 (4,) {}
1 2 3 (4,) {'e': 5}
函数返回值
函数中可以使用 return 返回结果:
def re_values(words):if "牛逼" in words:new_words = words.replace('牛逼', '厉害')return new_wordsresult = re_values("这次考试全班第一,非常牛逼")
print(result)
输出:
这次考试全班第一,非常厉害
如果返回多个值,将以元组形式保存:
def move(a, b, step):next_a = a + stepnext_b = b - stepreturn next_a, next_bresult = move(10, 20, 5)
print(result, type(result))
输出:
(15, 15) <class 'tuple'>
变量作用域
变量能否被访问取决于定义位置,这称为作用域。
局部变量与全局变量
#局部变量
def test():number=10print(number)def test2():number=20print(number)test()
test2()
#局部变量,函数用完即释放
print(number)#输出
10
20print(number)^^^^^^
NameError: name 'number' is not defined
全局变量示例:
number = 10
def test():global numbernumber +=1print('内部输出:',number)
test()
print('外部输出:',number)#输出
内部输出: 11
外部输出: 11
LEGB 原则
Python 搜索变量的顺序:
- L:Local(局部作用域)
- E:Enclosing(嵌套作用域)
- G:Global(全局作用域)
- B:Built-in(内置作用域)
import mathg_number = 10
def outer():e_number = 20def inner():l_number = 30print(l_number)print(math.pi)inner()print(e_number)
outer()
print(g_number)
global 与 nonlocal
# global 修改全局变量
number = 10
def test():global numbernumber += 1print(number)test()
print(number)
输出:
11
11
# nonlocal 修改嵌套作用域变量
def outer():number = 10def inner():nonlocal numbernumber = 20inner()print(number)outer()
输出:
20
特殊形式的函数
递归函数
函数自己调用自己:
#递归函数 5!
def func(num):#边界条件if num ==1:return 1else:#递推过程return num*func(num)num =int(input('请输入阶乘数值:'))
result=func(num)
print('结果:',result)
匿名函数
匿名函数用 lambda 定义:
tmp = lambda x:pow(x,2)
print(tmp(10))tmp = lambda x,y:x**y
print(tmp(10,3))#输出
100
1000
总结
- 函数定义:用
def关键字声明,格式为def 函数名([形参列表]): 函数体。支持无参函数(如def add():)和有参函数(如def add(a,b):),函数体需缩进。 - 函数调用:通过
函数名([实参列表])触发执行,如add(10,20)。支持嵌套调用(函数内部调用其他函数)和嵌套定义(函数内嵌套内层函数,内层仅能通过外层间接调用)。 - 参数传递 - 基础类型:位置传递(实参按顺序匹配形参,如
get_max(5,8));关键字传递(形参=实参,如connect(ip='127.0.0.1'));默认参数(定义时指定默认值,如def connect(ip,port=8080):)。 - 参数传递 - 打包与解包:
*args打包多个值为元组(如def test(*args):);**kwargs打包多个键值对为字典(如def test(**kwargs):);调用时用*解包元组、**解包字典(如test(*(1,2,3)))。 - 参数传递 - 混合规则:遵循 “位置参数→关键字参数→默认参数→打包参数” 顺序,定义时默认参数需在普通参数后,
*参数在默认参数后,**参数在*参数后。 - 返回值:用
return语句返回数据,如return a+b。返回多个值时默认封装为元组(如return next_a, next_b),执行return后函数立即终止。 - 变量作用域分类:局部变量(函数内定义,仅函数内有效,执行后释放);全局变量(函数外定义,程序任意位置可访问);嵌套作用域变量(外层函数定义,供内层嵌套函数访问)。
- 变量作用域规则:搜索遵循 LEGB 原则(局部→嵌套→全局→内置)。函数内默认不能修改全局变量,嵌套内层不能直接修改外层变量。
- 作用域关键字:
global关键字(函数内声明变量为全局变量,实现修改);nonlocal关键字(嵌套内层修改外层函数定义的变量)。 - 递归函数:函数内部调用自身,需满足 “边界条件(终止规则)+ 递归公式(递推逻辑)”。执行分递推(向下拆解)和回溯(向上返回结果)两阶段,如阶乘、兔子数列计算。
- 匿名函数:用
lambda关键字定义,格式为lambda 形参列表: 表达式。无名称、函数体仅 1 个表达式,需通过变量保存调用(如temp = lambda x: x*2)。 - 函数核心作用:抽取重复代码减少冗余,实现模块化编程,让程序结构更清晰,提升开发效率与后期维护性。
文件与数据格式化
在程序运行过程中,数据往往需要保存到文件中,以便下次运行时能够读取。
文件操作是编程中最常用的功能之一,掌握文件的读写、关闭和异常处理,是 Python 编程的基础能力。
文件的打开与关闭
Python 使用 open() 函数打开文件,返回一个文件对象。
最常见的使用方式是:
f = open('test.txt', 'r')
其中:
'test.txt'表示文件名;'r'表示以只读模式打开。
常见的打开模式如下:
| 模式 | 含义 |
|---|---|
'r' | 只读模式(默认) |
'w' | 写入模式,若文件存在则覆盖 |
'a' | 追加模式,在文件末尾写入 |
'b' | 以二进制方式打开 |
'+' | 读写模式,可与其他模式组合使用 |
操作完成后应关闭文件,释放系统资源:
f.close()
也可以使用 with 语句自动关闭文件:
with open('test.txt', 'r') as f:content = f.read()print(content)
# 离开 with 块后文件自动关闭
文件写入
写入文件可使用 write() 或 writelines() 方法。
with open('data.txt', 'w') as f:f.write("Hello, Python!\n")f.write("文件写入示例\n")
运行后 data.txt 文件的内容为:
Hello, Python!
文件写入示例
writelines() 适合一次写入多行:
lines = ["第一行\n", "第二行\n", "第三行\n"]
with open('multi.txt', 'w') as f:f.writelines(lines)
文件读取
文件读取有多种方式:
1. 一次性读取整个文件:
with open('data.txt', 'r') as f:content = f.read()print(content)
2. 按行读取:
with open('data.txt', 'r') as f:for line in f:print(line.strip())
3. 使用 readline() 逐行读取:
with open('data.txt', 'r') as f:line1 = f.readline()line2 = f.readline()print(line1, line2)
4. 使用 readlines() 读取所有行:
with open('data.txt', 'r') as f:lines = f.readlines()print(lines)
文件指针操作
文件对象维护一个指针,记录当前读写位置。
可以使用以下方法控制它:
f.tell() # 查看当前指针位置
f.seek(0) # 将指针移动到文件开头
示例:
with open('data.txt', 'r') as f:print(f.read(5)) # 读取前5个字符print(f.tell()) # 输出指针位置f.seek(0)print(f.read(5)) # 再次读取前5个字符
处理二进制文件
图片、音频、视频等文件属于二进制文件,读写时需要加 'b' 模式:
with open('image.png', 'rb') as f:data = f.read(1024)print(len(data))
复制二进制文件:
with open('image.png', 'rb') as src, open('copy.png', 'wb') as dst:dst.write(src.read())
异常与安全处理
在文件操作中,文件可能不存在或权限不足,使用 try...except 可以避免程序异常终止:
try:with open('nofile.txt', 'r') as f:data = f.read()
except FileNotFoundError:print("文件不存在!")
except IOError:print("文件读写错误!")
数据格式化输出
Python 提供多种格式化输出方式,用于控制字符串的展示样式。
百分号格式化
name = "Tom"
age = 20
print("姓名:%s, 年龄:%d" % (name, age))
输出:
姓名:Tom, 年龄:20
format() 方法
print("姓名:{}, 年龄:{}".format("Alice", 23))
print("姓名:{0}, 年龄:{1}".format("Bob", 25))
f-string(推荐)
从 Python 3.6 起,推荐使用 f-string:
name = "Lily"
age = 18
print(f"姓名:{name}, 年龄:{age}")
支持表达式:
print(f"5 + 3 = {5 + 3}")
输出:
5 + 3 = 8
总结
- 文件概述:文件是存储在外部介质(如硬盘)的数据集合,标识由路径、文件名主干、扩展名组成。分为文本文件(可记事本读写)和二进制文件(需序列化 / 反序列化规则),物理层面均以二进制存储。
- 文件打开与关闭:用
open(file, mode)函数打开文件,mode指定读写模式(如r只读、w只写、a追加,加b为二进制模式、加+为可读可写)。关闭文件可通过close()方法,或with语句自动关闭,避免资源占用和数据丢失。 - 文件读取操作:
read(size)读取指定字节数据,缺省则读全部;readline()读取一行数据;readlines()读取所有行并返回列表。大文件建议分多次读取,避免耗尽内存,编码异常可通过chardet库检测编码解决。 - 文件写入操作:
write(data)写入字符串,返回写入字节数;writelines(lines)写入字符串或字符串列表,需显式指定换行符\n。文本文件需注意编码格式(如utf-8),避免乱码。 - 文件定位读写:
tell()获取当前读写位置(字节数);seek(offset, from)控制读写位置,from取 0(文件开头)、1(当前位置)、2(文件末尾),文本文件仅支持from=0,二进制文件无限制。 - 文件与目录管理:通过
os模块实现,remove()删除文件、rename()重命名文件、mkdir()/rmdir()创建 / 删除目录、getcwd()获取当前目录、chdir()更改默认目录、listdir()获取目录下文件列表。 - 数据维度分类:一维数据(线性对等,如列表、元组)、二维数据(关联两个参数,如矩阵、CSV 表格)、多维数据(复杂结构,如字典)。
- 一二维数据存储与读写:一维数据用英文半角分隔符(逗号、空格等)存储;二维数据常用 CSV 格式(逗号分隔字段,一行对应一条记录)。读取时按分隔符拆分数据,写入时按格式组织数据。
- 多维数据格式化:常用 JSON 格式(键值对组织,直观且流量消耗少),通过
json模块实现转换。dumps()将 Python 对象转为 JSON 字符串,loads()将 JSON 字符串解析为 Python 对象。 - 核心作用:文件实现数据持久化存储(程序结束后数据不丢失),数据格式化规范数据组织形式,便于存储、读取和跨平台 / 程序交换。
