Python Based on C
第一章:编写简单的程序
1.1:注释
对于python来说,注释符号是#和""" """
#coding=gbk
arr=[["数学",150],["英语",600]]
arr.sort(key=lambda x:x[1],reverse=True)
print(arr)
arr2=["语文。102"]
arr3=arr+arr2
"""print(arr3)
print(arr)
print(arr2)"""
1.2:标识符及其命名规则
与C语言基础规则相同:字母或_开头,含数字,字母,下划线。pyhton支持汉字作为标识符,但要小心软件兼容性问题,通常还是English合理
给变量或者函数等命名的时候尽量避免_dog_,_fish这样子的标识符,合法但是是有特殊意义,内建标识符使用的符号。
1.2.2:关键字/保留字
python语言完整关键字列表可以在IDLE中输入:
import keyword
print(keyword.kwlist)
输出:
['False', 'None', 'True', '__peg_parser__', 'and', 'as', 'assert', 'async', 'await', 'break', 'class', 'continue', 'def', 'del', 'elif', 'else', 'except', 'finally', 'for', 'from', 'global', 'if', 'import', 'in', 'is', 'lambda', 'nonlocal', 'not', 'or', 'pass', 'raise', 'return', 'try', 'while', 'with', 'yield']
请按任意键继续. . .
1.3变量与赋值语句
Pyhthon语言中的变量是用来标识对象或引用对象的
Pyhthon语言是动态类型语言,即变量不需要显式声明数据类型,根据变量的赋值,Python语言的解释器会自动确定其数据结构。
通过内置的type函数查看类型:
m=2.343234
print(type(m))

此外,python也没那么无脑,同C一样,是一种强类型语言,只该类型运行的运算操作;字符型无法与float,int等类型做计算。

1.3.2变量的赋值
与C一样,没啥好说的
1.3.3链式赋值语句
x=y=z=200没有问题,不会报错
而X=200,Y=200,Z=200则是会报错的,这一点与C语言不同

1.3.4解包赋值语句

这里,列了几个就要写几个值,如果a,b=1,那么就会报错,不会给b自动赋值为0
利用解包赋值语句对两个变量进行交换:连临时变量都不需要,真的cool
a=1
b=0
print("a=",a,"b= ",b)
a,b=b,a
print("a=",a,"b= ",b)
1.4数据的输入与输出
1.4.1输入函数input()+eval作用.
格式:变量=Input(”提示字符串“)比较牛逼的是这个提示字符串是可以自己在终端显示出来的
这样子的Input只能够得到文本(字符型),如果想要得到数字或者进行+-运算,需要使用eval
且eval只能处理字符串,如果用来处理已经是数字类型的变量就会报错。

1.4.2 输出函数print()
与printf类似,但是不需要占位符。
sep:用来设定以什么字符间隔输出对象,默认是一个空格
end:用来设定以什么字符作为输出对象的结尾,默认是换行符”\n“,也可以换其他字符串。

与C语言一致,如果要打印什么文本类的话,需要用引号,不然会被当作未被定义的变量。
特殊用法:与if else语句联立,可以少写一组嵌套,但一般不用,容易不合规

1.4.2.1f-string(格式化字符串字面量)
是 Python 3.6 及以上版本引入的特性,比传统的占位符更直观
核心用法
在字符串前加 f 或 F,用 {} 包裹变量或表达式,直接嵌入输出内容:
name = "李婷婷"
age = 18
print(f"他的名字是{name},今年{age}岁") # 输出:他的名字是李婷婷,今年18岁
进阶用法
{} 里还可以写表达式、调用函数:
a = 3
b = 5
print(f"a + b = {a + b}") # 输出:a + b = 8
print(f"姓名大写:{name.upper()}") # 输出:姓名大写:李婷婷
| 方式 | 语法示例 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|---|
| % 占位符 | print("名字:%s,年龄:%d" % (name, age)) | 经典语法,兼容 Python 2.x | 可读性差,占位符类型需严格匹配 | 老代码维护、简单快速格式化 |
str.format() | print("名字:{},年龄:{}".format(name, age)) | 灵活,可通过索引 / 关键字复用参数 | 写法稍繁琐,大段字符串时不够直观 | 需要复杂格式控制的场景 |
| f-string | print(f"名字:{name},年龄:{age}") | 可读性最强,支持直接嵌入表达式 | 仅支持 Python 3.6+ | 绝大多数现代 Python 开发 |
1.4.2.2print & if:三元运算符
可以将 if-else 逻辑浓缩成一行,直接嵌入 print() 或 f-string 中:
1. 基础语法
# 格式:结果1 if 条件 else 结果2
score = 85
print("及格" if score >= 60 else "不及格") # 输出:及格
2. 结合 f-string 使用
age = 17
print(f"你是{'成年人' if age >= 18 else '未成年人'}") # 输出:你是未成年人
3. 进阶:嵌套三元逻辑(不推荐过度使用,影响可读性)
score = 78
print("优秀" if score >= 90 else "良好" if score >= 80 else "及格")
1.5数值
1.5.1数据数值类型
计算机中存储和操作的信息通常称为数据
没啥好说的,与C一样,跳过了
1.5.2内置的数值操作
+,-,*,
/实数除法
//整除
取余%
**(乘方)2**3=8 比C语言方便太多了还是
2.内置的数值运算函数
| 函数名 | 功能说明 | 代码示例 |
|---|---|---|
abs(x) | 求 x 的绝对值 | abs(-7) → 7 |
round(x) | 四舍五入为整数;round(x,n) 保留 n 位小数 | round(3.67) → 4 |
pow(x,y) | 计算 x 的 y 次方(等价 x**y) | pow(2,4) → 16 |
divmod(x,y) | 同时返回 (商,余数) | divmod(13,4) → (3,1) |
max(...) | 取一组数 / 序列的最大值 | max(5,9,2) → 9 |
min(...) | 取一组数 / 序列的最小值 | min(5,9,2) → 2 |
sum([.....]) | 对可迭代对象(列表 / 元组等)求和 | sum([1,2,3]) → 6 |
int(x) | 转为整数(截断小数) | int(6.99) → 6 |
float(x) | 转为浮点数 | float(8) → 8.0 |
bin(x) | 转为二进制字符串(以 0b 开头) | bin(12) → '0b1100' |
oct(x) | 转为八进制字符串(以 0o 开头) | oct(12) → '0o14' |
hex(x) | 转为十六进制字符串(以 0x 开头) | hex(12) → '0xc' |
代码验证:

1.5.3使用math库
不支持复数类型,仅支持整数和浮点数运算,需要使用import引入math库才可以引用
引用方式1:
import math
print(math.pi)
引用方式2:
from math import pi
print(pi)
最好用:from math import*一劳永逸,不需要像1一样加前缀,也不需要像2一样只能对单
2.math库中的数学常数与函数
| 常量写法 | 含义 | 近似值 |
|---|---|---|
math.pi | 圆周率 π | 3.14159265… |
math.e | 自然常数 e | 2.71828182… |
math.tau | 2π(一圈的弧度数) | 6.28318530… |
math.inf | 正无穷大 | ∞ |
math.nan | 非数值(Not a Number) | — |
| 函数写法 | 功能说明 |
|---|---|
math.sqrt(x) | 求 x 的算术平方根 |
math.pow(x, y) | 求 x 的 y 次方(浮点型) |
math.exp(x) | 求 e^x |
math.log(x) | 求 x 的自然对数(ln x) |
math.log10(x) | 求 x 以 10 为底的对数 |
math.log2(x) | 求 x 以 2 为底的对数 |
math.fabs(x) | 求 x 的绝对值(返回浮点数) |
math.factorial(x) | 求 x 的阶乘(x 为非负整数) |
math.ceil(x) | 向上取整(往大的方向取) |
math.floor(x) | 向下取整(往小的方向取) |
math.trunc(x) | 截断取整(直接去掉小数部分) |
math.sin(x) | 正弦函数(x 为弧度) |
math.cos(x) | 余弦函数(x 为弧度) |
math.tan(x) | 正切函数(x 为弧度) |
math.asin(x) | 反正弦函数(返回弧度) |
math.acos(x) | 反余弦函数(返回弧度) |
math.atan(x) | 反正切函数(返回弧度) |
math.radians(deg) | 角度 → 弧度转换 |
math.degrees(rad) | 弧度 → 角度转换 |
math.hypot(x, y) | 求 √(x²+y²)(平面两点距离) |
math.gcd(a, b) | 求 a、b 的最大公约数 |
math.isfinite(x) | 判断 x 是否为有限数 |
math.isnan(x) | 判断 x 是否为 nan |
代码验证:
from math import*
print(nan)
print(pi)
print(e)
print(inf)
print(pow(2,3))
print(exp(2))
print(sqrt(3.12))
print(log(9,3))
print(log2(4))
print(log10(10))
print(degrees(pi))
print(radians(180))
print(hypot(3.1,2))
print(sin(pi/2))
print(cos(pi/2))
print(tan(pi/2))
print(asin(0))
print(acos(0))
print(atan(0))

1.6字符串及其“+”号拼接作用
使用单引号或双引号引起来的内容,称为字符串类型数据(str),python语言的解释器会自动创建str类型对象示例。
单引号:' '可包含双引号
双引号:'' ''可包含单引号
三单引号:''' '''可包含单引号双引号可跨行
三双引号:""" """可包含单引号双引号可跨行
没啥特别好讲的
1.换行机制
2.当两个紧邻的字符串,如果中间只有空格分隔,则自动拼接为一个字符串‘中国’
3.C语言中的转义字符python也使用。

python的语言非常的简易,甚至你可以用“+”号来进行字符串的拼接,相当夸张。
1.6.2字符串的索引与切片
python的索引与C语言不同,分为正向与反向索引
正向:从0到最后
反向:从右往左,最右边那个为-1,依次减1
字符串的切片访问:格式s[n1:n2] 此时不包n2,实际是从下标n1到下标n2-1
若n1缺失,则表示从头开始,若n2缺失,则表示一次性读到结尾。
字符串的复杂切片访问:s[n1:n2:n3] n3为步长,当n1小于n2时期,若n3为负数,则啥都取不到,输出空白。其他的倒是没有什么好说的,代码验证一下。

# coding=gbk
m=int(input("请输入一个1-12间的整数"))
months="janfebmaraprmayjunjulaugsepoctnovdec"
pos=(m-1)*3
print(months[pos:pos+3])
示例:python神力
1.6.3字符串处理与操作
+拼接
* 字符串复制
in判断是否为子串
chr(x)返回Unicode编码为x的字符
ord(x)返回字符的unicode的编码
python的字符串是不可变的,所以字符串对象提供的涉及字符串“修改”的方法都是返回修改之后的新字符串,并不对原字符串做任何修改。
| 方法 | 作用 | 示例 |
|---|---|---|
s.isalpha() | 判断是否全为字母 | "abc".isalpha() → True |
s.isdigit() | 判断是否全为数字 | "123".isdigit() → True |
s.isalnum() | 判断是否字母 + 数字(无符号) | "abc123".isalnum() → True |
s.isspace() | 判断是否全为空白字符(空格 / 制表符) | " ".isspace() → True |
s.islower() | 判断是否全小写 | "abc".islower() → True |
s.isupper() | 判断是否全大写 | "ABC".isupper() → True |
s.istitle() | 判断是否标题格式(首字母大写) | "Hello World".istitle() → True |
s.startswith(prefix) | 判断是否以指定前缀开头 | "test.py".startswith("te") → True |
s.endswith(suffix) | 判断是否以指定后缀结尾 | "test.py".endswith(".py") → True |

| 方法 | 作用 | 示例 |
|---|---|---|
s.find(sub) | 查找子串首次出现索引,找不到返回 -1 | "hello".find("l") → 2 |
s.index(sub) | 同 find,找不到抛异常 | "hello".index("e") → 1 |
s.rfind(sub) | 查找子串最后出现索引 | "hello".rfind("l") → 3 |
s.rindex(sub) | 同 rfind,找不到抛异常 | - |
s.count(sub) | 统计子串出现次数 | "hello".count("l") → 2 |

| 方法 | 作用 | 示例 |
|---|---|---|
s.lower() | 转全小写 | "HELLO".lower() → "hello" |
s.upper() | 转全大写 | "hello".upper() → "HELLO" |
s.capitalize() | 首字母大写,其余小写 | "hello".capitalize() → "Hello" |
s.title() | 每个单词首字母大写 | "hello world".title() → "Hello World" |
s.swapcase() | 大小写互换 | "AbC".swapcase() → "aBc" |

| 方法 | 作用 | 示例 |
|---|---|---|
s.split(sep) | 按分隔符拆分为列表 | "a,b,c".split(",") → ["a","b","c"] |
s.rsplit(sep) | 从右往左拆分 | "a,b,c".rsplit(",",1) → ["a,b","c"] |
sep.join(iterable) | 用分隔符拼接可迭代对象 | ",".join(["a","b"]) → "a,b" |
s.partition(sep) | 分割为 **(前,分隔符,后)** 三元组 | "a-b-c".partition("-") → ("a","-","b-c") |
|
| 从右往左分割三元组 | - |

其中slipt函数可以设置最大值,即maxslipt,如示例
| 方法 | 作用 | 示例 |
|---|---|---|
s.strip() | 去除首尾空白字符 | " hello ".strip() → "hello" |
s.lstrip() | 去除左侧空白 | - |
s.rstrip() | 去除右侧空白 | - |
s.center(width) | 居中对齐 | "hi".center(5) → " hi " |
s.ljust(width) | 左对齐 | "hi".ljust(5) → "hi " |
s.rjust(width) | 右对齐 | "hi".rjust(5) → " hi" |
s.zfill(width) | 左侧补 0 到指定长度 | "123".zfill(5) → "00123" |
第二个参数可以规定拿什么东西来填充,值得注意的是如果想用空格,必须“ ”,不输入空白字符会报错,没用默认这一说法
1.6.4format()格式化方法
新增一种格式化字符串的方法str.format(),它增强了字符串格式的功能,基本语法是通过{}和:来代替之前的“%d”.format可以有多个输出。
"待格式化字符串{占位符1}{占位符2}".format(参数1, 参数2, ...)
- 字符串中的
{}= 占位符 format()里的参数会按顺序 / 按名称填入{}
1. 空占位符(按顺序匹配)
不写编号 / 关键字,format 参数从左到右依次填入。
# 示例
print("我叫{},今年{}岁,来自{}".format("张三", 20, "上海"))
# 输出:我叫张三,今年20岁,来自上海
2. 位置编号占位符({0}、{1}、{2}...)
手动指定参数索引,可重复使用、可调整顺序。
# 调整顺序
print("{1} 比 {0} 大".format(18, 22))
# 输出:22 比 18 大
# 重复使用
print("{0}{0}{1}".format("A", "B"))
# 输出:AAB
3. 关键字占位符({key})
用关键字参数填充,可读性极强,顺序无关。
print("姓名:{name},成绩:{score},班级:{cls}".format(
name="李四",
score=98.5,
cls="计科1班"
))
# 输出:姓名:李四,成绩:98.5,班级:计科1班
三、容器解包(列表 / 元组 / 字典)
format 支持直接解包列表、元组、字典,不用逐个传参。
1. 列表 / 元组解包(*)
# 元组
info = ("王五", 21, "北京")
print("姓名:{},年龄:{},城市:{}".format(*info))
# 列表
lst = [90, 80, 70]
print("语文:{},数学:{},英语:{}".format(*lst))
2. 字典解包(**)
stu = {"name": "赵六", "age": 19, "major": "计算机"}
print("姓名:{name},年龄:{age},专业:{major}".format(**stu))
四、核心进阶:格式控制符(重点)
这是 format 最强大的部分,语法:
{[索引/关键字]:[填充][对齐][宽度][.精度][类型]}
从左到右依次控制:填充字符 → 对齐方式 → 总宽度 → 小数精度 → 数据类型
1. 对齐 + 填充 + 宽度
|
符号 |
含义 |
|---|---|
|
|
左对齐(默认) |
|
|
右对齐 |
|
|
居中对齐 |
|
数字 |
总宽度 |
|
字符 |
填充字符(仅 1 个) |
# 左对齐,宽度10(默认空格填充)
print("{:<10}".format("hello")) # 输出:hello
# 右对齐,宽度10,填充*
print("{:*>10}".format("hello")) # 输出:*****hello
# 居中对齐,宽度10,填充-
print("{:-^10}".format("hello")) # 输出:--hello---
2. 精度控制(.n)
-
浮点数:保留
n位小数 -
字符串:截取前
n个字符
# 浮点数保留2位小数
print("{:.2f}".format(3.1415926)) # 输出:3.14
# 字符串截取前3个字符
print("{:.3}".format("python")) # 输出:pyt
3. 数字类型格式化
|
类型符 |
含义 |
示例 |
|---|---|---|
|
|
十进制整数 |
|
|
|
二进制 |
|
|
|
八进制 |
|
|
|
小写十六进制 |
|
|
|
大写十六进制 |
|
|
|
浮点数 |
|
|
|
百分比(自动 ×100) |
|
|
|
小写科学计数法 |
|
|
|
大写科学计数法 |
|
|
|
数字千分位分隔 |
|
# 进制转换
print("10的二进制:{:b}".format(10)) # 1010
print("10的十六进制:{:X}".format(10)) # A
# 百分比
print("正确率:{:.1%}".format(0.925)) # 92.5%
# 千分位
print("金额:{:,}".format(12345678)) # 12,345,678
五、高级用法
1. 直接调用对象属性
class Student:
def __init__(self, name, score):
self.name = name
self.score = score
s = Student("孙七", 95)
print("姓名:{s.name},分数:{s.score}".format(s=s))
# 输出:姓名:孙七,分数:95
2. 日期时间格式化
配合 datetime 模块直接格式化日期:
from datetime import datetime
now = datetime.now()
print("当前时间:{:%Y-%m-%d %H:%M:%S}".format(now))
# 输出:2026-03-30 15:30:00(示例)
常用日期符:%Y年、%m月、%d日、%H时、%M分、%S秒
1.7混合运算和类型转换
int和float可以类型自动转换

Python强转格式与C语言不同,C语言是对类型加括号,但PYTHON是对于数字加括号。
且char类型和int,float无法相互转换,会直接报错。
第二章 程序流程控制
这里的核心是由于python结构中不需要{}来控制结构,所以缩进即代表语句的并列关系,需要着重注意缩进
2.1条件表达式
2.1.1关系运算符
等于不等于,大于等于小于等于啥的和C语言一样
python中关系运算符是可以连用的!非常的人性化,字符与数值之间不可以比较大小,字符串的比较大小相当于C语言中的strcpy函数,非常的方便!

2.1.2逻辑运算符
&&类比and
||类比or
!类比not取反
2.1.3布尔类型
python语言中Bool类型数值使用常量Ture和False来表示,注意这里的False和Ture首字母必须大写。关系运算符返回的就是布尔类型。对于数值来说,False=0,Ture=1
2.2选择结构
2.2.1:if语句
if 条件表达式:
语句块
2.2.2双分支结构:if-else语句
if 条件表达式:
语句块1
else:
语句块2
小应用:判断回文字符串(你会发现比C语言简直简单太多了)
# coding=gbk
str=input("请输入字符串")
if str==str[::-1]:
print("回文")
else:
print("不是回文")
2.2.3多分支语句:if-elif-else语句
elif为else if的缩写,可以有很多个
if 条件:
语句块1
elif 条件:
语句块2
else:
语句块n
同时,if的语句与C语言一样都可以嵌套,此时要格外注意缩进,以免出岔子。
2.3循环结构
2.3.1 for语句+range函数
for语句用一个循环控制器来描述其语句块的重复式
for 变量 in 迭代器
语句块
for in都是关键字
1.字符串作为迭代器,怎么不算一种贼简单的遍历呢
2.range函数生成迭代序列
range()是python语言中的一个内置函数,调用这个函数就能产生一个迭代序列,因此适合放在for语句的头部。
range(n):0-n-1
range(m,d) 实则是左开右闭
range(m,n,z) m~n-1,z为步长
与for语句搭配可以达到C语言中常用的for循环,如果只是需要一个循环来控制语句块的循环次数,而不关心循环变量本身的取值,可以写for i in range(10) 它等价于for i in range(0,10,1)
# coding=gbk
sum=0
for i in range(100):
sum=sum+i
print(sum)
2.3.2 while语句
格式:while 条件表达式:
语句块
其余用法与C相似,不做赘述,代码自看,别写个死循环出来就行。
# coding=gbk
sum=0
i=1
while i<=100:
sum=sum+i
i=i+1
print(sum)
2.3.3 break和continue语句
与C语言没差。也是都只能出现在循环体内,且只能控制包含着它们的最内层循环。对我来说比较新奇的是求一个数的最大公因数的代码
# coding=gbk
n=eval(input("请输入一个整数"))
m=eval(input("请输入另一个整数"))
for i in range(min(m,n),0,-1):
if n%i==0 and m%i==0:
break
print("{}和{}的最大公约数为{}".format(n,m,i))
2.3.4循环结构中的else子句(与C语言有差异!)
现在有两种退出for循环或者while循环,一是循环条件不成立或序列遍历结束,另一种是在循环过程中遇到了break语句
# coding=gbk
for i in range(5):
print(i,end=" ")
else:
print("for循环正常结束")
for i in range(5):
print(i,end=" ")
if(i>=3):
break
else:
print("for循环正常结束")
2.3.5循环的嵌套+pyhthon中的换行符
和C语言没啥区别的,python中print()和C语言中printf("\n")一个效果。()里面有没用space都无所谓
2.4random库的基本应用
pyhthon语言内置的random库提供了与随机数有关的功能。
| 分类 | 函数名 | 核心作用 | 语法 / 区间 | 示例 | 关键备注 |
|---|---|---|---|---|---|
| 随机种子 | seed(n) | 固定随机序列,调试复用 | random.seed(整数) | seed(10) | 种子相同→每次随机结果一模一样 |
| 随机浮点数 | random() | 生成 0~1 随机小数 | 左闭右开 [0.0, 1.0) | random() | 无参数,最基础浮点 |
uniform(a,b) | 生成 a~b 随机浮点数 | 自动适配大小 [min,max] | uniform(2,6) | 可正可负 | |
| 随机整数 | randint(a,b) | 闭区间随机整数 | 全包 [a, b] | randint(1,5) | 高频考点,包含首尾 |
randrange(start,stop,step) | 按步长取随机整数 | 左闭右开 [start, stop) | randrange(0,10,2) | 等价:randint(a,b)=randrange(a,b+1) | |
| 序列操作 | choice(seq) | 随机选1 个元素 | 字符串 / 列表 / 元组 | choice([1,2,3]) | 抽 1 个,可重复 |
choices(seq,k=n) | 选 n 个,可放回重复 | k = 选取个数 | choices([A,B],k=3) | 有放回抽样 | |
sample(seq,k=n) | 选 n 个,无放回不重复 | k≤序列总长 | sample([1,2,3],2) | 不能超长度 | |
shuffle(list) | 原地打乱列表顺序 | 仅可变列表 | shuffle(lst) | 直接改原列表,无返回值;字符串 / 元组不能用 |
除了uniform和randint其他全都是左闭右开,他俩是全闭。
代码示例:
# coding=gbk
from random import*
#seed(10)添加了seed无论运行多少次都是一样子的,这就是seed的作用
n=random()
print(n)
m=uniform(1,2)
print(m)
n=randrange(0,10,2)
print(n)
o=randint(1,100)
print(o)
print(sample("abcd",2))
list=['a','b','c','d']
print(shuffle(list))
print(choice("abcdef"))
print(choices("abcde",k=2))#这里k是权重,可以直接写,不用顾虑报错
random.shuffle() 是「原地修改列表」的函数,没有返回值(返回 None),你直接打印它的调用结果,就会输出 None。可以先打乱再打印。

第三章 函数
3.1函数的基本概念
没啥好说
3.2函数的使用:
def 函数名([形参列表]):
函数体
3.2.1函数的默认参数:
在声明函数时,如果希望函数的一些参数是可选的,则可以在声明函数时为这些参数指定默认值。
def babble(words,times=1):
print((words+"")*times)
babble('123')
babble('123',2)
这里需要注意的是,函数的默认值必须写在形参列表的右边,这是因为在函数调用时,默认是按位置传递实际参数值的
如果默认参数在左,就会直接报错。
3.2.2函数的关键字参数
函数调用时,实参默认按照位置顺序传递参数,按照位置传递的参数为位置参数。函数调用时,也可以通过关键字指定传入的参数,按照关键字指定传入的参数称为关键字参数,也可以称为名称参数
示例:

有了关键字参数的话可以乱序书写,不需要位置传参一一对应,这一点比C强
3.2.3函数返回多个值
在python中,函数可以利用return返回多个值(完爆C语言)
F1:利用索引
F2:通过解包赋值,直接按顺序赋予
def function():
a=1
b=2
return a,b
print(function()[0])
print(function()[1])
c,d=function()
print(c,d)
0
3.3变量的作用域(重点:global关键字)
非常重要,函数的重难点皆于此,但由于与C类似,只做小差别说明
全局变量与局部变量的区别务必搞清楚,在局部变量与全局变量同名的时候,局部变量屏蔽全局变量,简称“局部有限”
如果一定需要用,则需要关键字global来声明
简单解释一下:这里的global就直接把下面的x=10拿来用了,导致x=10执行不到,内部外部和返回值都与5有关。
3.4递归函数
与C语言类似,这里用一个递归求最大公约数的代码示例,不多做赘述。
3.5 lambda函数
lambda函数是一种简便的,在同一行定义函数的方法,实际上是生成一个函数对象,即匿名函数,广泛用于需要函数对象作为参数或函数比较简单并且只使用一次的场合
语法:lambada 参数1 参数2....:<函数语句>
示例:
#coding=gbk
f=lambda x,y:x*y
print(type(f))
print(f(1,2))
f2=lambda s:s[0]+s[1]
print(f2('我的天'))
第四章:列表与元组
列表(list)用来有序存放一组相关数据,以便进行统一的处理。
4.1列表介绍与元素访问
4.1.1列表的表示
将一组数据放在一对方括号“[]”中即定义了一个列表。
甚至于:python语言中允许存放不同类型的元素或者允许列表充当元素(这个直接相当于C中的结构体了,非常人性化)
也可以将列表中的元素一个个定义之后再进行汇编:
#coding=gbk
player1=['数学',100]
player2=['英语四级',600]
players=[player1,player2]
print(players)
此即为python列表
4.1.2元素的索引与访问
列表中每个元素都对应一个位置编号,这个位置称为元素的索引(与字符串类似,不做过多赘述)
以代码举例:
#coding=gbk
months=["JANUARY","FEBRUARY","MARCH","APRIL","MAY","JUNE","JULY","AUGUST","SEPTEMBER","OCTOBER","NOVEMBER","DECEMBER"]
i=eval(input("请输入月份"))
print("当前是{}".format(months[i-1]))
4.2:操作列表元素
4.2.1修改元素:
与C语言类似,不记
4.2.2增加元素(append与insert)
1.append()方法:列表专属方法之一,用来指定列表尾部,即当前最后一个元素的后面,追加指定新元素。
列表名.append(新元素)
示例:
#coding=gbk
months=["JANUARY","FEBRUARY","MARCH","APRIL","MAY","JUNE","JULY","AUGUST","SEPTEMBER","OCTOBER","NOVEMBER"]
months.append("DECEMBER")
i=eval(input("请输入月份"))
print("当前是{}".format(months[i-1]))
2.insert:允许为新增的元素指定加入位置
格式:列表名.insert(索引,新元素)
#coding=gbk
months=["FEBRUARY","MARCH","APRIL","MAY","JUNE","JULY","AUGUST","SEPTEMBER","OCTOBER","NOVEMBER"]
months.append("DECEMBER")
months.insert(0,"JANUARY")
i=eval(input("请输入月份"))
print("当前是{}".format(months[i-1]))

4.2.3删除元素(del,pop,remove)
1.del命令:python语言内置,用于删除指定的列表元素
语法:del 列表名[索引]
#coding=gbk
months=["JANUARY","FEBRUARY","MARCH","APRIL","MAY","JUNE","JULY","AUGUST","SEPTEMBER","OCTOBER","NOVEMBER","DECEMBER","DECEMBER"]
#months.append("DECEMBER")
#months.insert(0,"JANUARY")
#i=eval(input("请输入月份"))
#print("当前是{}".format(months[i-1]))
del months[12]
print(months)

用这个来删除多余的一个十二月
2.使用pop()
pop方法是指定索引从列表中删除该元素,并返回该元素
语法:列表名.pop(索引)
#coding=gbk
months=["JANUARY","FEBRUARY","MARCH","APRIL","MAY","JUNE","JULY","AUGUST","SEPTEMBER","OCTOBER","NOVEMBER","DECEMBER","DECEMBER"]
#months.append("DECEMBER")
#months.insert(0,"JANUARY")
#i=eval(input("请输入月份"))
#print("当前是{}".format(months[i-1]))
a=months.pop(12)
print(months)
print(a)

列表pop()指定索引来删除元素,当缺省指定索引时,将默认删除列表最末尾的元素
3.使用remove方法
当元素个数较多时,remove可以直接删除指定的值,当remove()方法指定的待删除元素值出现相同项时,删除索引值较小的元素
#coding=gbk
months=["JANUARY","FEBRUARY","MARCH","APRIL","MAY","JUNE","JULY","AUGUST","SEPTEMBER","OCTOBER","NOVEMBER","DECEMBER","DECEMBER"]
#months.append("DECEMBER")
#months.insert(0,"JANUARY")
#i=eval(input("请输入月份"))
#print("当前是{}".format(months[i-1]))
#a=months.pop(12)
months.remove("DECEMBER")
print(months)
#print(a)
4.2.4其他常用操作(len,in,not in,index,count)
没啥好说的,与对字符串的操作类似。
4.3操作列表
4.3.1遍历(解决谁是小偷)
1.使用range函数
#coding=gbk
months=["JANUARY","FEBRUARY","MARCH","APRIL","MAY","JUNE","JULY","AUGUST","SEPTEMBER","OCTOBER","NOVEMBER","DECEMBER","DECEMBER"]
months.remove("DECEMBER")
for i in range(0,12):
print("{}月是{}".format(i+1,months[i]))

2.直接的元素遍历
#coding=gbk
months=["JANUARY","FEBRUARY","MARCH","APRIL","MAY","JUNE","JULY","AUGUST","SEPTEMBER","OCTOBER","NOVEMBER","DECEMBER","DECEMBER"]
months.remove("DECEMBER")
for i in months:
print(i)

谁是小偷:警察A,B,C,D抓了四个人,只有一个人是真正的小偷,审问记录如下:
A:我不是小偷 B:C是小偷 C:小偷是D D:C在冤枉人
三真一假,问谁是小偷:
suspects=["A","B","C","D"]
for x in suspects:
if (x!="A") + (x=="C" )+ (x=="D")+(x!="D")==3:
print("小偷是:",x)
最终小偷是C
4.3.2列表排序(sort,sorted,lambda指定)
sort()是列表用来进行元素排序的方法:
列表.sort([key][,reverse]) True降序,False升序
对这里的逗号进行讲解:
书本上的 sorted(列表[,key][,reverse]) 是一种语法约定的表示方式,不是实际要写的代码。这里的符号有特殊含义,专门用来描述「可选参数」的用法:
符号含义解释
-
方括号
[ ]:表示「里面的内容是可选的」(可以写,也可以不写)。 -
逗号
,:放在方括号内,表示「如果要写这个参数,需要在前一个参数后面加逗号」;如果不写这个参数,逗号也不用加。
书本上的写法是语法说明,目的是告诉你:
-
key和reverse是可选的; -
如果用多个可选参数,需要用逗号隔开;
-
方括号和里面的逗号不需要真的写在代码里。
缺省reverse时,默认是升序排序,列表元素为嵌套结构时
key 接受一个函数(通常是 lambda 或内置函数),这个函数会作用于列表中的每一个元素,生成一个「中间键值」。排序时,Python 会根据这些「中间键值」的大小来排列原列表的元素,而不是直接比较元素本身,需要指定排序关键字key,如果缺省,默认以元素索引为0的子元素关键字进行排序。
#coding=gbk
arr=[2,4,1,3,12,3,1,3,4,13]
arr.sort()
print(arr)
arr.sort(reverse=True)
print(arr)

2.sorted()对指定的列表进行排序。
sorted(列表[,key][,reverse]),他只生成排序后的列表副本,不改变元列表中元素的顺序,类似于值传递,形参
#coding=gbk
arr=[2,4,1,3,12,3,1,3,4,13]
arr2=sorted(arr)
print("原来的数组还是为",arr)
print("新的的数组为",arr2)

3.使用lambda函数指定排序关键字
对于汉字,全部转为ord类型作大小排序,此时如果是汉字的话则会影响排序的值,需要通过简易的lambda创建函数来确认key进行排序
arr=[["数学",150],["英语",600]]
arr.sort(key=lambda x:x[1],reverse=True)
print(arr)

4.3.3列表切片
列表[头:尾:步长]与字符串完全一致,不做赘述
4.3.4列表的扩充(+,extend,*)
1.+运算
与算术运算的加法类似,此处的“+”也可以用来将两个列表加起来,只不过列表的加确切地说是指列表的连接。“+”运算可以将两个列表连接生成一个新列表,但是那两个列表本身并没有变化。
#coding=gbk
arr=[["数学",150],["英语",600]]
arr.sort(key=lambda x:x[1],reverse=True)
print(arr)
arr2=["语文。102"]
arr3=arr+arr2
print(arr3)
print(arr)
print(arr2)

2.extend()方法
"+"运算必须通过赋值语句才能将结果写入guests列表,而extend()方法可以直接将新的列表添加至guests列表的后面。
语法:列表.extend(新列表)
#coding=gbk
arr=[["数学",150],["英语",600]]
arr.sort(key=lambda x:x[1],reverse=True)
print(arr)
arr2=["语文,102"]
arr.extend(arr2)
print(arr)

3."*"运算
与字符串类似,列表的乘法运算是指将列表中的元素重复多遍
格式:列表*n
#coding=gbk
arr=[["数学",150],["英语",600]]
arr.sort(key=lambda x:x[1],reverse=True)
print(arr)
arr2=["语文,102"]
arr.extend(arr2)
arr=arr*3
print(arr)

“*”运算与“+”运算一致,如果不用赋值语句将结果赋给具体的列表,“*”运算的结果仅回显一次,不会被保存。
4.3.5列表的复制(共享列表,copy(),补充:索引)
1.直接的列表赋值
与C语言不同,在python中,赋值的本质是让“变量”能“引用指定的数据空间。所以,赋值语句“arr1=arr”是让变量"arr1"能引用arr指定的数据空间。即两个列表共享同一片列表空间,类比于C中的联合体/指针操作/malloc赋值。
#coding=gbk
arr=[["数学",150],["英语",600]]
arr.sort(key=lambda x:x[1],reverse=True)
print(arr)
arr1=arr
del arr[0]
print(arr)
print(arr1)

2.copy()方法
复制出一个新的列表空间,和原列表guests引用的空间互相独立,互不干涉
#coding=gbk
arr=[["数学",150],["英语",600]]
arr.sort(key=lambda x:x[1],reverse=True)
print(arr)
arr1=arr.copy()
del arr[0]
print(arr)
print(arr1)

3.自己补充:索引赋值
#coding=gbk
arr=[["数学",150],["英语",600]]
arr.sort(key=lambda x:x[1],reverse=True)
print(arr)
arr1=arr[:]
print(arr1)

4.3.6列表生成式
其主要的实现思想是遍历原列表,通过对原列表各元素的处理来生成新列表的元素。
新列表=[新列表元素表达式 for 元素变量 in 原列表]
#coding=gbk
arr=[["数学",150],["英语",600]]
arr.sort(key=lambda x:x[1],reverse=True)
print(arr)
arr1=[item[0:2] for item in arr]
print(arr1)

此外,如果配合if语句,列表生成式还可以对元素进行进一步的筛选,语法上类似于print&if那一节
#coding=gbk
arr=[100,600,300,200]
arr1=[item for item in arr if item>200]
print(arr1)

4.3.7列表的删除(clear(),del,)
1.clear
删除列表中的所有元素,可以用之前的删除方法,也可以使用clear()一键清空。
#coding=gbk
arr=[100,600,300,200]
arr1=[item for item in arr if item>200]
arr1.clear()
print(arr1)

2.del 彻底删除列表
彻底删除列表不仅删除列表中的所有元素,同时从内存中删除列表本身
#coding=gbk
arr=[100,600,300,200]
arr1=[item for item in arr if item>200]
arr1.clear()
del arr1
print(arr1)
4.4数值列表:eval(input()),list(),列表生成式
存放了一组相关的数值型元素
创建:
1.通过Input()输入
因为input函数只能收到字符串,可以使用eval()函数来进行转换.
#coding=gbk
arr=(input("请输入数值列表"))
print(arr)
print(type(arr))
arr=eval(arr)
print(arr)
print(type(arr))

2.通过list()函数转换,将字符串/range系列等等转换为列表
#coding=gbk
num=range(1,11)
print(num)
print(type(num))
num=list(num)
print(num)
print(type(num))

3.通过列表生成式生成
#coding=gbk
num=[i for i in range(0,11)]
print(num)

4.5元组(tuple)
1.元组使用圆括号(),列表使用方括号[]
2.元组的元素不能修改
3.其余与列表一致
4.5.1定义元组
1.将多个元素用“,”隔开放在()中
2.不带括号也可以,直接用,隔开
3.当定义的元组只有一个元素
#coding=gbk
tuple1=("子羽")
print(type(tuple1))
tuple1=("子羽",)
print(type(tuple1))
tuple2="子羽"
print(type(tuple2))
tuple2="子羽",
print(type(tuple2))
4.5.2操作元组(仅与列表对比)
以下是 列表(List) 与 元组(Tuple) 的核心操作对照表,重点对比因 “可变性” 差异导致的函数 / 方法区别:
5.5.5.
| 操作类型 | 列表(List) | 元组(Tuple) | 核心说明 |
|---|---|---|---|
| 定义方式 | lst = [1, 2, 3] 或 lst = list() | tup = (1, 2, 3) 或 tup = tuple() | 元组用 (),列表用 [];单元素元组需加逗号 (1,) |
| 访问元素 | lst[0]、lst[1:3](索引 / 切片) | tup[0]、tup[1:3](索引 / 切片) | 两者均为有序序列,支持完全相同的访问方式 |
| 增加元素 | lst.append(4)(末尾追加)lst.extend([5,6])(批量追加)lst.insert(1, 99)(指定位置插入) | ❌ 无任何增删方法(不可变)仅可通过 + 拼接生成新元组:new_tup = tup + (4,5) | 列表可变,支持原地增;元组不可变,只能生成新对象 |
| 删除元素 | lst.remove(2)(按值删除)lst.pop(0)(按索引删除并返回)lst.clear()(清空列表)del lst[1](删除指定索引) | ❌ 无任何删除方法(不可变)仅可通过 del tup 删除整个元组对象 | 列表支持原地删;元组只能整体删除,不能删单个元素 |
| 修改元素 | lst[0] = 99(索引赋值)lst[1:3] = [88,77](切片赋值) | ❌ 不支持任何修改(不可变)尝试修改会报错 TypeError | 核心差异:列表可变,元组不可变 |
| 查找元素 | lst.index(2)(返回值的第一个索引)lst.count(2)(统计值出现次数) | tup.index(2)(返回值的第一个索引)tup.count(2)(统计值出现次数) | 两者查找方法完全一致 |
| 排序 / 反转 | lst.sort()(原地排序,无返回值)lst.reverse()(原地反转) | ❌ 无原地排序 / 反转方法需通过 sorted(tup) 返回新列表,或 reversed(tup) 返回迭代器 | 列表支持原地修改顺序;元组只能生成新的有序对象 |
| 拼接 / 重复 | lst + [4,5](拼接生成新列表)lst * 2(重复生成新列表) | tup + (4,5)(拼接生成新元组)tup * 2(重复生成新元组) | 两者均支持 + 和 *,但均生成新对象,不修改原数据 |
| 长度 / 最值 | len(lst)、max(lst)、min(lst) | len(tup)、max(tup)、min(tup) | 通用内置函数,两者完全一致 |
| 互相转换 | list(tup)(元组转列表) | tuple(lst)(列表转元组) | 可通过 list() 和 tuple() 灵活切换 |
| 拷贝操作 | lst.copy() 或 lst[:](浅拷贝) | ❌ 无需拷贝(因不可变,直接赋值 tup2 = tup1 无副作用) | 元组不可变,无需担心联动修改;列表可变,需注意深浅拷贝 |
4.5.3元组充当列表元素
用法与列表相同,注意不要尝试修改元组的数据,不然会报错,不做赘述
4.6转换函数tuple(),list(),字符串split()
4.6.1元组与列表之间的转换
tuple1=("天子",)
print("转换前为",type(tuple1))
tuple1=list(tuple1)
print("转换后为",type(tuple1))
list1=["天子"]
print("转换前为",type(list1))
list1=tuple(list1)
print("转换后为",type(list1))
4.6.2字符串与列表之间的转换
#coding=gbk
str="天子"
print(type(str))
str=list(str)
print(type(str))
str=tuple(str)
print(type(str))
4.6.3字符串使用split()方法转换成列表格式
列表=字符串.split(分隔符)
分隔符如果缺省,默认按照空格拆分字符串
#coding=gbk
str="天子"
print(str)
print(type(str))
str=str.split()
print(str)
print(type(str))
4.7列表与函数(修正教材误导性:增强赋值运算符与普通赋值)
4.7.1可变类型作实参和不可变类型作实参(教材P129页内容错误)
人话:目前学到现在,数值型,字符串,元组都为不可变,只有列表是可变类型,后续还有字典,集合,字节数组,自定义类是可变的
一、先搞清楚:为什么教材的代码能得到它说的结果?
教材里用的是增强赋值运算符 x *= 2,而你之前写的是普通赋值 x = x * 2。这两个写法在 Python 中对于可变对象的行为天差地别。
|
代码 |
列表的行为 |
内存地址变化 |
外部变量是否变化 |
|---|---|---|---|
|
|
调用列表的 |
地址不变 |
✅ 外部列表会变 |
|
|
调用列表的 |
地址改变 |
❌ 外部列表不变 |
错误 1:把 "增强赋值的特性" 说成了 "可变对象的特性"
教材原文:"由于 x 引用的是可变的列表空间,因此会将运算结果直接写入 x 引用的空间、覆盖原来的值。"
这是完全错误的因果关系。
-
不是因为列表是可变的,所以
x *= 2就会原地修改 -
而是因为
*=这个增强赋值运算符,对于可变对象默认实现为原地修改 -
如果你用普通赋值
x = x * 2,即使是可变的列表,也会创建新对象,外部完全不受影响
错误 2:最终总结完全颠倒了因果
教材原文:"可变类型作实参,实参变量的值将跟随形参的变化而发生变化。"
这是 Python 初学者被误导最多的一句话。这句话是错的。
✅ 正确的终极结论:
在 Python 中,无论什么类型作实参,只要你对形参进行重新赋值,实参永远不会变;只有当你对形参指向的可变对象本身进行原地修改时,实参才会看到变化。
错误 3:遗漏了最关键的判断标准
教材完全没有区分 "原地修改" 和 "重新赋值" 这两个完全不同的操作,这是所有误解的根源。
三、用代码彻底推翻教材的错误结论
我们用同一个函数,传入同一个列表,只改一行代码,就能得到完全相反的结果:
# 教材的写法:增强赋值,原地修改
def test_book(x):
x *= 2 # 原地修改
ls = [1, 2]
test_book(ls)
print(ls) # 输出 [1, 2, 1, 2] (和教材一致)
# 你的写法:普通赋值,创建新对象
def test_your(x):
x = x * 2 # 重新赋值
ls = [1, 2]
test_your(ls)
print(ls) # 输出 [1, 2] (和教材结论矛盾)
这直接证明了:不是可变类型作实参就一定会被修改,而是要看你对它做了什么操作。
判断函数内的操作会不会影响外部变量,永远不要看它是不是可变对象,只看你做的是哪类操作:
✅ 原地修改操作(会影响外部可变对象)
-
列表 / 字典 / 集合的内置方法:
.append(),.extend(),.pop(),.remove(),.update(),.clear() -
增强赋值运算符:
x += ...,x *= ...(仅对可变对象有效) -
切片赋值:
x[:] = ... -
元素 / 键值赋值:
x[0] = ...,x['key'] = ...
❌ 重新赋值操作(永远不会影响外部任何变量)
-
任何形式的普通赋值:
x = ... -
普通运算赋值:
x = x + ...,x = x * ...(即使是可变对象) -
任何让变量
x指向一个新对象的操作
4.7.2可变参数
定义函数时:前面带*的称为可变参数,用来接收个性不确定的参数,发生函数调用的时候,可变参数将收集所有未匹配的参数组成与一个元组对象传入函数。
#coding=gbk
def test1(*x):
print(len(x))
print(type(x))
test1('a')
test1('a',1,2)

当函数有多个形参且包含可变参数的时候,可变参数只能写在最右侧
如果希望被可变参数收集的是列表中的多个元素,那么实参列表就要前面加“*”进行元素解包。
#coding=gbk
def test1(*x):
print(len(x))
print(type(x))
l=[1,2,3]
test1(l)
test1(*l)
第五章:字典与集合
5.1字典的创建与访问
5.1.1创建字典dict()函数
字典由键与值构成
键具有唯一性
字典中的键必须是不可变类型,所有列表不可以作为键
dictory={键1:值1,键2:值2.....}
F1:
#coding=gbk
dictory={"赵":"1","钱":'2'}
print(dictory)
print(type(dictory))

F2:将一组双元素序列转化为字典
#coding=gbk
dictory={"赵":"1","钱":'2'}
list1=["孙","李"]
list2=[1,2]
dictory1=dict(zip(list1,list2))
print(dictory1)

F3:也可以直用双元素嵌套序列作为参数调用dict()函数生成字典
#coding=gbk
dictory={"赵":"1","钱":'2'}
list1=["孙","李"]
list2=[1,2]
dictory1=dict(zip(list1,list2))
list3=[("赵",1),("钱",2)]
list3=dict(list3)
print(list3)
55
5.1.2访问字典
字典中的若干条目都是无序的。这意味着字典没有索引的概念,它不通过索引访问条目,而是通过键访问: 字典名[键]
#coding=gbk
dictory={"赵":"1","钱":'2'}
print(dictory["赵"])

如果用了一个不存在的键则会引起系统报错,而试图用索引访问字典,也是一个错误的操作。
如果要访问的字典中的值是一个序列,可以进一步通过索引访问值序列中的子元素。
#coding=gbk
dictory={"赵":[1,"one"],"钱":[2,"two"]}
print(dictory["赵"][1])

5.2字典的基本操作
字典存放的是数据与数据之间的映射关系,对应的条目是“键值对”,所以字典的操作都会涉及“键”和值两个部分
5.2.1字典更新
添加条目与修改条目
字典名[键]=值(当键不存在时是添加,存在时是修改)
5.2.2删除字典条目(del,pop(),popitem,clear,直接删除整个字典)
1.del 字典名[键]
字典名.pop(键,默认值)
与之前类似,它在删除指定键的对应的条目的时候会返回条目的值,如果键不存在,则返回默认值。如果不存在也不给默认值就会报错,且pop()最少要有一个指定参数。
2.字典名.popitem()
直接随机删除并返回某个完整的条目,且该条目会以完整的元组形式返回
3.字典名.clear()
一次性清空整个字典
4.del 字典名
5.销毁
#coding=gbk
dictory1={}
print(type(dictory1))
dictory={"赵":[1,"one"],"钱":[2,"two"]}
dictory["孙"]=[3,"three"]
print(dictory)
del dictory["孙"]
print("删除后为",dictory)
s=dictory.pop("孙",0)
print(s)#没找到孙,返回默认值
m=dictory.popitem()
print(dictory)#删一个
print(m)#剩一个
dictory.clear()#清空
print(dictory)
del dictory
print(dictory)

5.2.3查找字典条目
1.成员运算符 in
键 in 字典
在查找对应条目时可以用in运算符确认指定的键是否在字典中,存在为ture,不存在为false
#coding=gbk
dictory1={}
print(type(dictory1))
dictory={"赵":[1,"one"],"钱":[2,"two"]}
s="钱" in dictory
print(s)

2.用get()方法获取条目的值
字典名.get(键,默认值)
如果不存在,则返回默认值,当get()方法缺省了默认值,而指定的键不存在时,则执行语句但不返回任何信息。
#coding=gbk
dictory1={}
print(type(dictory1))
dictory={"赵":[1,"one"],"钱":[2,"two"]}
s="钱" in dictory
print(s)
s=dictory.get("孙")
M=dictory.get("赵")
print(s,M)

5.3字典的整体操作
1.遍历字典中的所有键keys()
for key in dictory.keys()
2遍历字典中所有的值values()
注:values()方法虽然可以遍历字典中的所有的值,但是值无法映射到对应的键,因而无法遍历完整的条目信息.
3.遍历字典中的所有的条目items()
4 k-v遍历
#coding=gbk
dictory1={}
print(type(dictory1))
dictory={"赵":[1,"one"],"钱":[2,"two"]}
for key in dictory.keys():
print(key)
for key in dictory.values():
print(key)
for key in dictory.items():
print(key)
for k,v in dictory.items():
print("姓为{}排序为{}".format(k,v))
6.3.2字典的排序
严格来说字典是不支持排序的,人们只能将字典中的条目按照人们希望的顺序进行显示。
内置函数sorted()可以将字典的键排序并以列表的形式返回。(只有键,如果需要条目则需要其他操作)
#coding=gbk
dictory1={}
print(type(dictory1))
dictory={"赵":[1,"one"],"钱":[2,"two"]}
ls=sorted(dictory)
print(ls)
print(type(ls))
for surname in ls:
print(dictory[surname])

亦可借用lambda函数:
#coding=gbk
dictory1={}
print(type(dictory1))
dictory={"赵":[1,"one"],"钱":[2,"two"]}
t=list(dictory.items())
print(t)
t.sort(key=lambda x:x[1],reverse=True)
print(t)

6.3.3字典的合并update,dict()
1.使用字典的update()方法
将一个字典中的条目合并进另一个字典中,参数字典不变,只更新主字典
字典名.update(参数字典名)
#coding=gbk
dictory1={}
print(type(dictory1))
dictory={"赵":[1,"one"],"钱":[2,"two"]}
dictory2={"孙":[3,"three"]}
dictory.update(dictory2)
print(dictory)

2.使用内置函数dict()
新字典=dict(字典1,**字典2)
#coding=gbk
dictory1={}
print(type(dictory1))
dictory={"赵":[1,"one"],"钱":[2,"two"]}
dictory2={"孙":[3,"three"]}
dictory3=dict(dictory,**dictory2)
print(dictory3)
print(dictory)
print(dictory2)
**:将字典解包成关键字"孙=[3,"three"]"
上述两种方法更准确的说是字典的扩充,条目的增加。一般来说参加合并的两个字典的键是互不相同的。如果两个字典中出现了相同的键,那么合并后只会有一组包含该键的条目被保留下来。
3.按键进行的字典合并(双保留)
#coding=gbk
dictory1={}
print(type(dictory1))
dictory1={"赵":1}
dictory2={"赵":"one"}
dictory3={}
for k,v in dictory1.items():
dictory3[k]=[v,dictory2[k]]
print(dictory3)

5.4集合
集合被用来存放一组无序且互不相同的元素,同时,组成集合的元素必须是不可变类型。
主要用来关系运算和消除重复元素。
5.4.1集合的创建与访问
1.直接创建集合和创建空集合
变量={元素1,元素2,......}
变量=set()
2.用set()创建集合
python语言中用set()来将序列转换为集合,在转换过程中重复的元素只会保留1个
3.集合的访问
集合的元素是无序的,所以要么通过集合名作整体输出,要么通过for循环实现元素遍历
#coding=gbk
s={1,1}
print(s)
s1=set("hello")
print(s1)
s2=set()
print(type(s2))
for i in s1:
print(i,end=" ")

5.4.2集合的基本操作
1.添加元素
s.add(参) 将参数一整坨加进去
s.update(参) 将参数拆分去重后加进去
2.删除元素
s.remove(参) 将指定参数删除,如果不存在将报错
s,discard(参) 不存在不会报错
s.pop()随机删除,并且返回
s.clear() 全删
成员判断:item in S
#coding=gbk
s={1,2,3}
s.add(4)
s.update([5,5,6,7])
print(s)
s.remove(7)
s.discard(8)
print(s.pop())
if 1 in s:
s.remove(1)
print(s)
5.4.3 集合的数学运算
| 运算 | 数学符号 | Python 运算符 | |||
|---|---|---|---|---|---|
| 并集 | A∪B | A|B | |||
| 交集 | A∩B | A & B | |||
| 差集 | A−B | A - B | |||
| 对称差集 | A△B | A ^ B |
#coding=gbk
s={1,2,3}
m={1,3,5}
print(s|m)
print(s&m)
print(s-m)
print(s^m)

5.4.4字典与可变集合
字典作参数时,与列表作类比。当为可变参数的时候,前面需要加**
可变形参依然只遵循只能写在参数列表的最右边这一点
#coding=gbk
def mysum(dictory):
sum=0
for i in dictory.values():
sum=sum+i
return sum
dictory={"语文":100,"数学":100}
print(mysum(dictory))

可变赋值:
#coding=gbk
def mysum(dictory):
sum=0
for i in dictory.values():
sum=sum+i
return sum
def my_sum(**dictory):
sum=0
for i in dictory.values():
sum=sum+i
return sum
print(my_sum(语文=100,数学=100))#此时关键字不需要加双引号
第六章:文件与异常
7.1文件基础知识
7.1.1文件与文件类型
主文件名.扩展名
一般来说,文件都是按文件名访问的,一方面通过主文件名指明访问对象,另一方面通过扩展名指定访问和处理文件的应用程序
7.1.2目录与文件路径
绝对路径:从文件所在驱动器名称(又称“盘符”)开始描述文件的保存位置。
两种绝对路径的表现形式:
r"E:\python\littletst"
E:\\python\\littletst
r表示取消后续字符串中反斜杠的转义特性。
相对路径:指从当前工作目录开始描述文件的保存位置,每个运行的程序都有一个当前的工作目录,又称为cwd python自带os库
#coding=gbk
import os
print(os.getcwd())
os.chdir('E:\\')
print(os.getcwd())#改变当前的工作目录,相当于移动参考系的原点.
此时再写相对位置就要从E\\之后开始写了。
7.2文件操作
7.2.1文件的打开与关闭
1.文件的打开
file 对象名=open(文件路径字符串,模式字符)
| 序号 | 打开模式 | 读写操作(权限) | 文件类型 | 文件不存在时 | 文件已存在时 | 是否覆盖原内容 | 初始文件指针 | 关键补充说明 |
|---|---|---|---|---|---|---|---|---|
| 1 | r | 只读,禁止写入 | 文本文件(str) | 抛出 FileNotFoundError 报错 | 保留全部原有内容 | ❌ 不覆盖 | 文件开头 | Python 默认打开模式,仅用于读取 |
| 2 | w | 只写,禁止读取 | 文本文件(str) | 自动创建空白新文件 | 立即清空所有原有内容 | ✅ 整体全覆盖 | 文件开头 | 打开瞬间就删原数据,谨慎使用 |
| 3 | a | 追加写,禁止读取 | 文本文件(str) | 自动创建空白新文件 | 保留全部原有内容 | ❌ 不覆盖 | 文件末尾 | 新内容永远追加在文件最后 |
| 4 | r+ | 可读 + 可写 | 文本文件(str) | 抛出 FileNotFoundError 报错 | 保留全部原有内容 | ⚠️ 局部覆盖 | 文件开头 | 不会清空文件;从开头写入会覆盖对应位置字符 |
| 5 | w+ | 可读 + 可写 | 文本文件(str) | 自动创建空白新文件 | 立即清空所有原有内容 | ✅ 整体全覆盖 | 文件开头 | 等价于 w 模式 + 额外增加读取权限 |
| 6 | a+ | 可读 + 追加写 | 文本文件(str) | 自动创建空白新文件 | 保留全部原有内容 | ❌ 不覆盖 | 文件末尾 | 可移动指针读取内容;写入强制跳转到文件末尾 |
| 序号 | 打开模式 | 读写操作(权限) | 文件类型 | 文件不存在时 | 文件已存在时 | 是否覆盖原内容 | 初始文件指针 | 关键补充说明 |
|---|---|---|---|---|---|---|---|---|
| 7 | rb | 只读,禁止写入 | 二进制文件(bytes) | 抛出 FileNotFoundError 报错 | 保留全部原有内容 | ❌ 不覆盖 | 文件开头 | 读取图片、音视频必备,无编码参数 |
| 8 | wb | 只写,禁止读取 | 二进制文件(bytes) | 自动创建空白新文件 | 立即清空所有原有内容 | ✅ 整体全覆盖 | 文件开头 | 二进制专属覆盖写入 |
| 9 | ab | 追加写,禁止读取 | 二进制文件(bytes) | 自动创建空白新文件 | 保留全部原有内容 | ❌ 不覆盖 | 文件末尾 | 二进制文件末尾追加数据 |
| 10 | rb+ | 可读 + 可写 | 二进制文件(bytes) | 抛出 FileNotFoundError 报错 | 保留全部原有内容 | ⚠️ 局部覆盖 | 文件开头 | 不清空文件,指针处局部改写二进制数据 |
| 11 | wb+ | 可读 + 可写 | 二进制文件(bytes) | 自动创建空白新文件 | 立即清空所有原有内容 | ✅ 整体全覆盖 | 文件开头 | 二进制版 w+,打开即清空原文件 |
| 12 | ab+ | 可读 + 追加写 | 二进制文件(bytes) | 自动创建空白新文件 | 保留全部原有内容 | ❌ 不覆盖 | 文件末尾 | 可读可追加;写入依旧强制到文件末尾 |
2.文件的关闭
执行open打开文件后,这个文件就被Python程序占用并调入内存,当读写操作结束后,必须将文件从内存保存回外存,此时就要关闭文件
file 对象.close()
7.2.2写文件
1.file 对象的write()方法写文件
file对象.write(写入字符串)
1.打开文件执行写入操作的时候,连续的write()方法将按照顺序依次写入字符串
2.文件的write()方法将指定的字符串参数原因写入文件,连续写入的不同字符串之间不会添加任何分隔符
2用file对象的writelines()方法写文件
file对象.writelines(字符串序列)
与write()方法相比,writelines()方法可以以序列的形式接收多个字符串作为参数,一次写入多个字符
写入时期也都无任何分隔符,所以只有在列表参数的每个字符串末尾加上分隔符才可。
7.2.3读文件
1.用file对象的read()方法读文件
读出文件所有内容并作为一个字符串返回
字符串变量=file对象.read()
2.用file对象的readline()方法读文件
列表变量=file对象.readlins()
readline()方法将读出文件中当前行,并以字符串的形式返回。
因此如果想获取所有的文件,只用readline需要for循环。

采用a+形式,运行之后直接新建一个文件.

#coding=gbk
import os
print(os.getcwd())
file=open("E:\\python\\littletst\\mytxt","w+")#一开始没有,直接新建一个文本
file.write("有时我也会有点蓝色的小脾气\n")
file.writelines(["但你的一切我了解\n","每种都代表我对你的感觉\n"])#自己配置好换行符
file.seek(0)
s=file.read()
print(s)
file.seek(0)#文件指针涉及到C语言的内容,基本原理是每次运行完文件指针会抵达末尾,需要自行置于首位。
s1=file.readlines()
print(s1)
file.close()

7.3CSV文件
CSV 全称 Comma-Separated Values(逗号分隔值),是一种通用纯文本表格格式,广泛用于数据导入 / 导出、程序数据交互。
一、基础本体特征(文件本身属性)
-
文件类型 纯文本文件,非二进制文件,不存储字体、颜色、单元格样式、公式、图表等富格式,只保存原始字符数据。
-
文件后缀 标准后缀为
.csv;也存在衍生格式.tsv(制表符分隔)。 -
打开方式 任意文本编辑器(记事本、VS Code、Notepad++)、表格软件(Excel/WPS、金山表格)、编程语言均可直接读取。
-
兼容性 跨平台、跨软件通用,是不同程序之间传递表格数据的首选格式。
二、核心格式规则(CSV 最核心标准)
CSV 的本质:用符号拆分「行」和「列」,规则全球通用。
1. 行规则
文件中每一行 = 表格中的一条数据记录。
行与行之间依靠换行符分割
2. 列(字段)规则
同一行内的多个单元格(字段),默认使用 英文逗号 , 作为分隔符。
严禁使用中文逗号 ,,会导致解析失败。
标准示例(带表头)
姓名,语文,数学,英语
小明,98,95,92
小红,90,88,96
三、特殊字段转义规则(重点、考试 / 实操高频考点)
当字段内容本身包含逗号、换行、英文双引号时,不能直接书写,必须遵循转义规范,否则表格会错乱。
规则 1:字段含「英文逗号 / 换行符」→ 整段用英文双引号 " 包裹
场景:单元格内容里本身有逗号,直接写会被当成列分隔符。
❌ 错误写法:
昵称,签名
张三,你好,很高兴认识你 # 逗号被识别为新列,表格错位
✅ 正确写法(双引号包裹整段内容):
昵称,签名
张三,"你好,很高兴认识你"
拓展:如果字段内包含换行(单元格内换行),同样要用双引号包裹:
姓名,简介
李四,"爱好编程
喜欢Python"
规则 2:字段内含「英文双引号 "」→ 用两个连续双引号 "" 转义
CSV 规定:不能用反斜杠 \ 转义引号,必须双引号嵌套转义。
❌ 错误:"他说:""加油"" 或 他说:\"加油\" ✅ 正确:
内容
"他说:""加油""
规则 3:空字段规则
连续两个英文逗号 ,, 代表当前单元格为空。 示例(第二列、第四列为空):
姓名,语文,数学,英语
王五,,85,
四、表头规范(可选但行业通用)
-
表头不是强制要求:CSV 可以纯数据、无表头。
-
常规用法:文件第一行一般作为表头,用来定义每一列的名称(字段名)。
-
表头格式和普通数据行完全一致,同样遵循逗号分隔、引号转义规则。
98,95,92
90,88,96
五、数据类型特征(关键区别于 Excel)
-
CSV 无数据类型概念 所有内容(数字、文字、日期、编号)全部以「文本字符串」形式存储,没有整数、小数、日期、布尔值等类型区分。
-
当用 Excel/WPS 打开时,表格软件会自动猜测并转换数据类型,但源
.csv文件本身依旧是纯文本。
示例:123、00123 在 CSV 里都是普通字符串,Excel 打开后可能自动把 00123 变成数字 123(丢失前导零)。
7.4对CSV文件的操作
1.提供一种打开方式的自动挡
with open(文件路径字符串,模式字符) as 文件对象名
2.reader对象,引入csv
3.writer对象和writerow(),writerows将用列表存储的一行数据写入文件
#coding=gbk
import csv
with open ("E:\\python\\littletst\\mycsv","w+") as mycsv:
writer=csv.writer(mycsv)
writer.writerow([1,2,3])
writer.writerows([[4,5,6],[7,8,9]])
mycsv.seek(0)
reader=csv.reader(mycsv)
for i in reader:
print(i)

一、出现空列表的根本原因(来源AI,随便看看得了)
1. CSV 写入自带换行符机制
csv.writer 默认每行数据末尾都会自动添加换行符 \r\n(Windows 标准换行):
-
writerow([1,2,3])写入:1,2,3\r\n -
writerows([[4,5,6],[7,8,9]])分别写入:4,5,6\r\n、7,8,9\r\n最终文件完整内容:
1,2,3\r\n
4,5,6\r\n
7,8,9\r\n
文件最后还多了一组 \r\n,代表末尾存在一条空白空行。
2. csv.reader 读取规则
-
有内容的正常行 → 解析成数字列表
[1,2,3] -
纯换行的空白行 → 解析成空列表
[]所以循环打印会多出一行空列表。
二、分步还原你的代码执行流程
-
open(...,w+):清空文件,文件指针在开头位置 -
写入三行数据,每行结尾强制追加换行,文件末尾多出一个空换行
-
mycsv.seek(0):指针挪回文件最开头 -
csv.reader(mycsv)逐行读取全部内容,读到末尾空白行时返回[]
三、三种解决办法
方法 1:读取时过滤空列表(最简单推荐)
循环里加判断,只打印有内容的行:
#coding=gbk
import csv
with open("E:\\python\\littletst\\mycsv.csv","w+",encoding="gbk") as mycsv:
writer=csv.writer(mycsv)
writer.writerow([1,2,3])
writer.writerows([[4,5,6],[7,8,9]])
mycsv.seek(0)
reader=csv.reader(mycsv)
for i in reader:
if i: # 空列表布尔值为False,直接跳过
print(i)
方法 2:修改 writer 换行符,减少多余空行
给 writer 指定 lineterminator='\n',减少多余回车换行:
writer=csv.writer(mycsv,lineterminator='\n')
方法 3:写入结束后截断多余末尾空白
写入完成后把文件末尾多余字节裁掉,再读取:
writer.writerows([[4,5,6],[7,8,9]])
# 把当前指针位置设为文件末尾,裁掉多余换行
pos = mycsv.tell()
mycsv.truncate(pos)
mycsv.seek(0)
四、补充小知识点
-
空列表
[]不是程序 bug,是 CSV 空白行的标准解析结果; -
Linux/macOS 环境换行符是
\n,也一样会出现末尾空行问题; -
只有完全空白、无任何字符的行,reader 才会返回空列表;带空格的空行会返回
['']。
修正后无空列表的输出效果
['1', '2', '3']
['4', '5', '6']
['7', '8', '9']
注意:csv 读取出来的数字全部是字符串格式,CSV 本身不区分数字 / 文本类型。
7.5异常和异常处理
常见异常
| 异常名称 | 中文说明 | 典型触发场景 & 示例 |
|---|---|---|
Exception | 通用异常基类 | 所有常规业务异常的父类,可用来统一捕获大部分程序异常 |
ZeroDivisionError | 除零错误 | 算术运算中除数为 0示例:print(10 / 0) |
OSError(IO 相关) | 输入 / 输出、文件路径异常(原 IOError 已并入此类) | 文件不存在、路径错误、权限不足、目录操作失败示例:open("不存在的文件.txt", "r") |
IndexError | 索引下标越界 | 列表、字符串、元组使用了超出范围的索引示例:lst = [1,2]; print(lst[5]) |
KeyError | 字典键不存在 | 通过键访问字典,键名未定义示例:d = {"a":1}; print(d["b"]) |
NameError | 名称未定义 | 使用了未声明、未赋值的变量 / 函数示例:print(num)(变量 num 从未定义) |
异常处理:try语句
try:语句
except 异常名称:
捕获异常时处理
else:
未发生异常时处理
随便举个栗子吧
#coding=gbk
arr=[0,1,2,3]
for i in range(0,5):
try:
print(arr[i])
except IndexError:
print("打印时{}数组越界".format(i))
else:
print("打印时{}正常执行".format(i))
一些应用实例:
#coding=gbk
from math import*
def my_search(x,t):#二分查找
low=0
high=len(t)-1
while low<=high:
mid=(low+high)//2
if t[mid]<x:
low=mid+1
elif t[mid]>x:
high=mid-1
else:
return mid
return -1
def searchprime(n):#筛选法查找素数
mylist=[item for item in range(n)]
mylist[0:2]=[0,0]
for i in range(2,int(n**0.5)+1):
if mylist[i]!=0:
for j in range(i*i,n,i):
mylist[j]=0
print("{}以内的素数有:".format(n))
for _ in mylist:
if _!=0:
print(_,end=" ")
def isprime(n):#判断素数
if n<=1:
return 0
for i in range(2,int(n**0.5)+1):
if n%i==0:
return 0
return 1
def neiborprime(n):#n以内的相邻素数
for i in range(2,n-1):
if isprime(i) and isprime(i+2):
print("{}和{}是相邻素数".format(i,i+2))
def counttext(text):#统计文本内的大小写及数字
upper=0
lower=0
digit=0
for i in text:
if i.isupper():
upper+=1
if i.islower():
lower+=1
if i.isdigit():
digit+=1
print(f"大写字母个数为{upper}")
print(f"小写字母个数为{lower}")
print(f"数字个数为{digit}")
def S (a,b,c):#三角形abc面积
if(a+b>c and a+c>b and b+c>a and a>0 and b>0 and c>0):
h=(a+b+c)/2
return sqrt(h*(h-a)*(h-b)*(h-c))
else:
print("数据有误无法组成三角形")
return None
def shuixianhua( ):#水仙花数
for i in range(100,1000):
a=i//100
b=i//10%10
c=i%10
if a**3+b**3+c**3==i:
print("{}是水仙花数".format(i))
def wanshu(n):#完数
for i in range(1,n):
s=0
for j in range(1,i):
if i%j==0:
s+=j
if s==i:
print("{}是完全数".format(i))
def sumprime(n):#素数之和为该数
flag=0
for i in range(2,n//2+1):
if isprime(i) and isprime(n-i):
flag=1
print("{}可拆分为{}和{}的和".format(n,i,n-i))
if(flag==0):
print("未找到两个素数之和为{}".format(n))
def factoril(n):#递归求阶乘
if n==0 or n==1:
return 1
else:
return n*factoril(n-1)
def fibo(n):#递归求斐波拉契数列
if n==1 or n==2:
return 1
else:
return fibo(n-1)+fibo(n-2)
def gcd(a,b):#递归方法求最大公约数
if b==0:
return a
else:
return gcd(b,a%b)
def gtext(text):#把文本筛干净
text=text.lower()
for ch in ",.:;?-\'":
text=text.replace(ch," ")
return text
def wordfre(text,ceiling):#词频
words=text.split()
counts={}
for i in words:
counts[i]=counts.get(i,0)+1
excludes={"a","the","an","to","and","of"}
for i in excludes:
counts.pop(i,None)
l=list(counts.items())
l.sort(key=lambda x:x[1],reverse=True)
return l[:ceiling]
#对于文件的操作:
l=[]
try:
with open ("E:\\python\\文本.txt",'r') as file:
text=file.read()
text=gtext(text)
l=wordfre(text,1)
except IOError:
print("文件异常")
else:
try:
with open ("E:\\python\\词屏.txt",'w') as frequence:
items=[k+'\t'+str(v)+'\n'for k,v in l]
frequence.writelines(items)
except IOError:
print("写入文件出错")
for word,freq in l:
print("{}的出现频率为{}".format(word,freq))
def gettext():
try:
with open ("E:\\python\\满意程度.txt","r",encoding="utf-8") as file:
content=file.read().strip()
except IOError:
print("文件打开错误")
return []
else:
l=[item.strip() for item in content.split(",") if item.strip()]
return l
l=gettext()
dictory={}
for x in l:
dictory[x]=dictory.get(x,0)+1
verysatisfied=dictory.get("很满意",0)
satisfied=dictory.get("满意",0)
nosatisfied=dictory.get("不满意",0)
final=list(dictory.items())
final.sort(key=lambda x:x[1],reverse=True)
if final:
maxfre=max(final,key=lambda x:x[1])
else:
maxfre=None
try:
with open ("E:\\python\\满意程度统计.txt","w",encoding="utf-8") as writer:
lines=[k+'\t'+str(v)+"\n" for k,v in final]
writer.writelines(lines)
except IOError:
print("文件写入错误")
print("满意人数为{}".format(satisfied))
print("不满意人数为{}".format(nosatisfied))
print("很满意人数为{}".format(verysatisfied))
更多推荐



所有评论(0)