Python 从小白到大神:涵盖全面的语法大全
文章目录
摘要:本文是Python入门教程,系统讲解了字面量、注释、变量与标识符、数据类型、类型转换、运算符、字符串操作、文件读写及数据可视化等核心基础知识。通过大量代码示例和实战技巧,帮助初学者快速掌握Python编程基础。
一、字面量
什么是字面量?用一句话来说:字面量就是你在代码里直接写出来的固定值。
# 这些都是字面量
123 # 整数字面量
3.14 # 浮点数字面量
"hello" # 字符串字面量
True # 布尔值字面量
[1, 2, 3] # 列表字面量
{"name": "张三"} # 字典字面量
各种类型的字面量
# 整数字面量
age = 18
negative = -5
big_number = 1000000
# 浮点数字面量(小数)
pi = 3.14159
price = 99.99
scientific = 1.5e3 # 科学计数法,等于1500.0
# 字符串字面量
name = "小明"
message = 'Hello World'
multiline = """这是
多行
字符串"""
# 布尔值字面量(只有两个)
is_student = True
is_working = False
# 特殊字面量:None(表示"空"或"没有值")
result = None
二、注释
注释用来批注代码,让别人也能看懂你的代码,经常写注释是一个好习惯:
单行注释
# 这是单行注释,用井号开头
print("Hello") # 也可以写在代码后面
# 计算圆的面积
radius = 5
area = 3.14 * radius ** 2 # ** 是次方运算
多行注释
"""
这是多行注释
可以写很多行
通常用三个引号
"""
'''
单引号的三引号也可以
但一般用双引号比较多
'''
# 实际使用场景
def calculate_area(radius):
"""
计算圆的面积
参数:radius - 圆的半径
返回:圆的面积
"""
return 3.14 * radius ** 2
快捷键:在VSCode或PyCharm里,选中多行代码按Ctrl + /可以快速注释/取消注释。
三、变量&标识符
变量用来保存数据,请注意python的变量没有类型,只有数据才会有类型!
变量的基本使用
# 创建变量(赋值)
name = "张三"
age = 20
height = 1.75
# 使用变量
print(name) # 张三
print(age) # 20
# 变量可以改变
age = 21
print(age) # 21
# 变量可以参与运算
next_year_age = age + 1
print(next_year_age) # 22
标识符就是我们给变量、函数、类等起的名字。Python对标识符有严格的规定:
标识符的规则
-
字符范围:只能由 字母(a-z/A-Z)、数字(0-9)、下划线(_) 组成,且不能以数字开头。
正确:name、user_age、_score、Book123
错误:123name(数字开头)、user-age(含连字符)、my name(含空格)、价格(非ASCII字符,不推荐) -
大小写敏感:
Name和name是两个完全不同的变量。Name = "张三" name = "李四" print(Name) # 输出:张三 print(name) # 输出:李四 -
不能使用关键字:不能使用Python内置的关键字(保留字)作为变量/函数名,比如
if、else、for、while、def、class等。
可通过以下代码查看所有关键字:import keyword print(keyword.kwlist) # 输出Python所有保留字
命名建议:
- 用有意义的名字:
student_count比sc好理解 - 多个单词用下划线连接:
user_name(Python推荐) - 常量用大写:
PI = 3.14159 - 私有变量用下划线开头:
_internal_value
多个变量赋值
# 同时给多个变量赋值
x, y, z = 1, 2, 3
print(x, y, z) # 1 2 3
# 交换两个变量的值(这个太方便了!)
a = 10
b = 20
a, b = b, a # 不需要临时变量
print(a, b) # 20 10
# 给多个变量赋相同的值
x = y = z = 0
print(x, y, z) # 0 0 0
四、数据类型
Python有很多种数据类型,每种类型能做的事情不一样。
基本数据类型
# 数字类型
integer = 10 # int - 整数
floating = 3.14 # float - 浮点数(小数)
complex_num = 3 + 4j # complex - 复数
# 文本类型
text = "Hello" # str - 字符串
# 布尔类型
is_true = True # bool - 布尔值
is_false = False
# 序列类型
my_list = [1, 2, 3] # list - 列表(可变)
my_tuple = (1, 2, 3) # tuple - 元组(不可变)
my_range = range(5) # range - 范围
# 映射类型
my_dict = {"name": "张三"} # dict - 字典
# 集合类型
my_set = {1, 2, 3} # set - 集合
# 空值类型
nothing = None # NoneType - 空值
整数(int)
# 整数可以是正数、负数、零
positive = 100
negative = -50
zero = 0
# Python的整数没有大小限制!
huge = 123456789012345678901234567890
print(huge) # 完全没问题
# 不同进制的整数
binary = 0b1010 # 二进制,等于10
octal = 0o12 # 八进制,等于10
hexadecimal = 0xA # 十六进制,等于10
print(binary, octal, hexadecimal) # 10 10 10
浮点数(float)
# 小数
price = 19.99
pi = 3.14159
# 科学计数法
large = 1.5e3 # 1.5 × 10³ = 1500.0
small = 1.5e-3 # 1.5 × 10⁻³ = 0.0015
print(large, small) # 1500.0 0.0015
# 浮点数的精度问题(这个坑我踩过)
print(0.1 + 0.2) # 0.30000000000000004(不是0.3!)
# 解决方法:四舍五入
result = round(0.1 + 0.2, 2) # 保留2位小数
print(result) # 0.3
字符串(str)
# 单引号和双引号都可以
name1 = 'Alice'
name2 = "Bob"
# 字符串里有引号怎么办?
sentence1 = "He said 'Hello'" # 外面用双引号
sentence2 = 'She said "Hi"' # 外面用单引号
sentence3 = "He said \"Hello\"" # 用转义字符
# 多行字符串
poem = """床前明月光,
疑是地上霜。
举头望明月,
低头思故乡。"""
print(poem)
# 原始字符串(不转义)
path = r"C:\Users\name\Documents" # r前缀
print(path) # 反斜杠不会被转义
布尔值(bool)
# 只有两个值
is_student = True
is_teacher = False
# 比较运算返回布尔值
print(5 > 3) # True
print(5 < 3) # False
print(5 == 5) # True
# 逻辑运算
print(True and False) # False
print(True or False) # True
print(not True) # False
# 哪些值会被当作False?
print(bool(0)) # False
print(bool("")) # False(空字符串)
print(bool([])) # False(空列表)
print(bool(None)) # False
# 其他都是True
print(bool(1)) # True
print(bool("hello")) # True
print(bool([1, 2])) # True
列表(list)
# 创建列表
fruits = ["苹果", "香蕉", "橙子"]
numbers = [1, 2, 3, 4, 5]
mixed = [1, "hello", 3.14, True] # 可以混合类型
# 访问元素(索引从0开始)
print(fruits[0]) # 苹果
print(fruits[1]) # 香蕉
print(fruits[-1]) # 橙子(负数从后往前数)
# 修改元素
fruits[0] = "西瓜"
print(fruits) # ['西瓜', '香蕉', '橙子']
# 列表的长度
print(len(fruits)) # 3
元组(tuple)
# 元组和列表很像,但不能修改
point = (3, 5)
person = ("张三", 18, "学生")
# 访问元素
print(point[0]) # 3
# 不能修改
# point[0] = 10 # 报错!TypeError
# 单个元素的元组要加逗号
single = (5,) # 注意这个逗号
print(type(single)) # <class 'tuple'>
not_tuple = (5) # 这不是元组,只是数字5
print(type(not_tuple)) # <class 'int'>
字典(dict)
# 字典是键值对
student = {
"name": "小明",
"age": 18,
"grade": "高三"
}
# 访问值
print(student["name"]) # 小明
print(student["age"]) # 18
# 修改值
student["age"] = 19
# 添加新键值对
student["school"] = "一中"
# 删除键值对
del student["grade"]
print(student)
集合(set)
# 集合是不重复的元素
numbers = {1, 2, 3, 4, 5}
fruits = {"苹果", "香蕉", "橙子"}
# 自动去重
nums = {1, 2, 2, 3, 3, 3}
print(nums) # {1, 2, 3}
# 集合运算
a = {1, 2, 3}
b = {3, 4, 5}
print(a | b) # {1, 2, 3, 4, 5} 并集
print(a & b) # {3} 交集
print(a - b) # {1, 2} 差集
五、type()语句
type()函数可以告诉你一个变量是什么类型,这在调试时能起到关键作用。
# 查看各种类型
print(type(123)) # <class 'int'>
print(type(3.14)) # <class 'float'>
print(type("hello")) # <class 'str'>
print(type(True)) # <class 'bool'>
print(type([1, 2, 3])) # <class 'list'>
print(type((1, 2, 3))) # <class 'tuple'>
print(type({"a": 1})) # <class 'dict'>
print(type({1, 2, 3})) # <class 'set'>
print(type(None)) # <class 'NoneType'>
让我们来看看如何实际应用的:
# 实际应用
def process_data(data):
print(f"数据类型:{type(data)}")
if type(data) == int:
print("这是整数")
elif type(data) == str:
print("这是字符串")
process_data(100) # 数据类型:<class 'int'> 这是整数
process_data("hello") # 数据类型:<class 'str'> 这是字符串
# 更好的方法:用isinstance()
print(isinstance(123, int)) # True
print(isinstance("hi", str)) # True
print(isinstance([1, 2], list)) # True
六、类型转换
有时候需要把一种类型转换成另一种类型,比如把字符串转成数字。
转换成整数 - int()
# 字符串转整数
age_str = "18"
age = int(age_str)
print(age + 2) # 20
# 浮点数转整数(会丢失小数部分)
pi = 3.14
pi_int = int(pi)
print(pi_int) # 3
# 布尔值转整数
print(int(True)) # 1
print(int(False)) # 0
# 不能转换的情况
# int("hello") # 报错!ValueError
# int("3.14") # 报错!不能直接转,要先转成float
转换成浮点数 - float()
# 字符串转浮点数
price_str = "19.99"
price = float(price_str)
print(price) # 19.99
# 整数转浮点数
num = 10
num_float = float(num)
print(num_float) # 10.0
# 布尔值转浮点数
print(float(True)) # 1.0
print(float(False)) # 0.0
转换成字符串 - str()
# 数字转字符串
age = 18
age_str = str(age)
print("我今年" + age_str + "岁") # 我今年18岁
# 任何类型都能转成字符串
print(str(3.14)) # "3.14"
print(str(True)) # "True"
print(str([1, 2, 3])) # "[1, 2, 3]"
print(str({"a": 1})) # "{'a': 1}"
转换成布尔值 - bool()
# 数字转布尔值
print(bool(0)) # False
print(bool(1)) # True
print(bool(-5)) # True(非零都是True)
# 字符串转布尔值
print(bool("")) # False(空字符串)
print(bool("hello")) # True
# 列表转布尔值
print(bool([])) # False(空列表)
print(bool([1, 2])) # True
# None转布尔值
print(bool(None)) # False
转换成列表、元组、集合
# 字符串转列表
text = "hello"
chars = list(text)
print(chars) # ['h', 'e', 'l', 'l', 'o']
# 元组转列表
t = (1, 2, 3)
l = list(t)
print(l) # [1, 2, 3]
# 列表转元组
l = [1, 2, 3]
t = tuple(l)
print(t) # (1, 2, 3)
# 列表转集合(自动去重)
l = [1, 2, 2, 3, 3, 3]
s = set(l)
print(s) # {1, 2, 3}
# 集合转列表
s = {3, 1, 2}
l = list(s)
print(l) # [1, 2, 3](集合会自动排序)
八、运算符
运算符就是用来做运算的符号,Python有很多种运算符。
算术运算符
a = 10
b = 3
print(a + b) # 13 加法
print(a - b) # 7 减法
print(a * b) # 30 乘法
print(a / b) # 3.333... 除法(结果是浮点数)
print(a // b) # 3 整除(只要整数部分)
print(a % b) # 1 取余数(模运算)
print(a ** b) # 1000 幂运算(10的3次方)
比较运算符
a = 10
b = 5
print(a == b) # False 等于
print(a != b) # True 不等于
print(a > b) # True 大于
print(a < b) # False 小于
print(a >= b) # True 大于等于
print(a <= b) # False 小于等于
# 字符串也可以比较
print("abc" < "abd") # True(按字典序)
print("apple" == "apple") # True
# 链式比较(Python特有)
x = 5
print(1 < x < 10) # True(相当于 1 < x and x < 10)
print(10 < x < 20) # False
赋值运算符
# 基本赋值
x = 10
# 复合赋值
x += 5 # 相当于 x = x + 5
print(x) # 15
x -= 3 # 相当于 x = x - 3
print(x) # 12
x *= 2 # 相当于 x = x * 2
print(x) # 24
x /= 4 # 相当于 x = x / 4
print(x) # 6.0
x //= 2 # 相当于 x = x // 2
print(x) # 3.0
x %= 2 # 相当于 x = x % 2
print(x) # 1.0
x **= 3 # 相当于 x = x ** 3
print(x) # 1.0
逻辑运算符
# and:都为真才为真
print(True and True) # True
print(True and False) # False
print(False and False) # False
# or:有一个真就为真
print(True or False) # True
print(False or False) # False
# not:取反
print(not True) # False
print(not False) # True
# 实际应用
age = 20
has_id = True
if age >= 18 and has_id:
print("可以进入") # 输出这个
else:
print("不能进入")
# 短路运算
x = 0
y = 10
result = x and y # x是0(False),不会再看y
print(result) # 0
result = x or y # x是0(False),会看y
print(result) # 10
成员运算符
# in:检查是否在序列中
fruits = ["苹果", "香蕉", "橙子"]
print("苹果" in fruits) # True
print("西瓜" in fruits) # False
# not in:检查是否不在序列中
print("西瓜" not in fruits) # True
# 字符串中也可以用
text = "Hello World"
print("Hello" in text) # True
print("Python" in text) # False
# 字典中检查键
student = {"name": "张三", "age": 18}
print("name" in student) # True
print("grade" in student) # False
身份运算符
# is:检查是否是同一个对象
a = [1, 2, 3]
b = [1, 2, 3]
c = a
print(a == b) # True(值相同)
print(a is b) # False(不是同一个对象)
print(a is c) # True(是同一个对象)
# is not
print(a is not b) # True
# None的检查要用is
x = None
print(x is None) # True(推荐)
print(x == None) # True(不推荐)
运算符优先级
# 从高到低:
# 1. **(幂运算)
# 2. *, /, //, %(乘除)
# 3. +, -(加减)
# 4. ==, !=, >, <, >=, <=(比较)
# 5. not
# 6. and
# 7. or
# 示例
result = 2 + 3 * 4
print(result) # 14(先乘后加)
result = (2 + 3) * 4
print(result) # 20(括号优先)
result = 10 > 5 and 20 < 30
print(result) # True
# 复杂表达式建议加括号
result = ((10 + 5) * 2) > (20 - 5)
print(result) # True
九、字符串
字符串是我用得最多的类型之一,Python的字符串功能非常强大。
字符串的创建
# 单引号
name1 = 'Alice'
# 双引号
name2 = "Bob"
# 三引号(多行)
poem = """床前明月光,
疑是地上霜。
举头望明月,
低头思故乡。"""
# 转义字符
text = "第一行\n第二行" # \n是换行
print(text)
path = "C:\\Users\\name" # \\是反斜杠
print(path)
quote = "He said \"Hello\"" # \"是双引号
print(quote)
# 原始字符串(不转义)
path = R"C:\Users\name\Documents"
print(path) # 反斜杠不会被转义
字符串拼接
# 1. 使用 + 运算符(适合少量短字符串拼接)
str1 = "Hello"
str2 = "World"
result1 = str1 + " " + str2
print(result1) # 输出: Hello World
# 2. 使用 str.join() 方法(适合大量字符串拼接,性能最优)
parts = ["Hello", "World", "from", "Python"]
result2 = " ".join(parts)
print(result2) # 输出: Hello World from Python
# 3. 使用 f-string (Python 3.6 推荐)
name = "Alice"
age = 25
result3 = f"Name: {name}, Age: {age}"
print(result3) # 输出: Name: Alice, Age: 25
# 4. 使用 str.format() 方法
result4 = "Name: {}, Age: {}".format(name, age)
print(result4) # 输出: Name: Alice, Age: 25
# 5. 使用 % 格式化(旧式,不推荐但仍兼容)
result5 = "Name: %s, Age: %d" % (name, age)
print(result5) # 输出: Name: Alice, Age: 25
# 6. 多行字符串字面量自动拼接(无需运算符)
result6 = ("Hello "
"World "
"Auto")
print(result6) # 输出: Hello World Auto
# 错误1:字符串与非字符串类型直接 +
try:
result = "Age: " + 25 # 25是int,不能直接和str拼接
except TypeError as e:
print(f"错误1: {e}") # 输出: 错误1: can only concatenate str (not "int") to str
# 错误2:误用逗号拼接(得到的是元组,不是字符串)
result = "Hello", "World"
print(f"错误2: {result}, 类型: {type(result)}") # 输出: 错误2: ('Hello', 'World'), 类型: <class 'tuple'>
# 错误3:尝试通过索引修改字符串(Python字符串不可变)
try:
s = "Hello"
s[0] = "h" # 不可变对象不支持元素赋值
except TypeError as e:
print(f"错误3: {e}") # 输出: 错误3: 'str' object does not support item assignment
# 错误4:join() 传入包含非字符串元素的可迭代对象
try:
parts = ["Hello", 25, "World"]
result = " ".join(parts) # 25是int,join要求所有元素都是str
except TypeError as e:
print(f"错误4: {e}") # 输出: 错误4: sequence item 1: expected str instance, int found
# 错误5:join() 传入非可迭代对象
try:
result = " ".join("Hello") # 虽然字符串是可迭代的,但这会拆成字符,不是预期拼接;若传入数字会报错
# 更典型错误: " ".join(123)
result = " ".join(123)
except TypeError as e:
print(f"错误5: {e}") # 输出: 错误5: can only join an iterable
字符串的索引和切片
text = "Python"
# 索引(从0开始)
print(text[0]) # P
print(text[1]) # y
print(text[-1]) # n(最后一个)
print(text[-2]) # o(倒数第二个)
# 切片 [start:end:step]
print(text[0:3]) # Pyt(索引0到2)
print(text[:3]) # Pyt(省略start从头开始)
print(text[3:]) # hon(省略end到最后)
print(text[::2]) # Pto(步长为2)
print(text[::-1]) # nohtyP(反转字符串)
# 实际应用:提取文件扩展名
filename = "document.pdf"
extension = filename[-3:]
print(extension) # pdf
# 实际应用:隐藏手机号中间4位
phone = "13812345678"
hidden = phone[:3] + "****" + phone[7:]
print(hidden) # 138****5678
字符串的格式化
# 方法1:%格式化(老方法)
name = "张三"
age = 18
print("我叫%s,今年%d岁" % (name, age))
# 方法2:format()方法
print("我叫{},今年{}岁".format(name, age))
print("我叫{0},今年{1}岁,{0}很高兴认识你".format(name, age))
print("我叫{name},今年{age}岁".format(name=name, age=age))
# 方法3:f-string(推荐,Python 3.6+)
print(f"我叫{name},今年{age}岁")
print(f"明年我{age + 1}岁") # 可以包含表达式
字符串格式化的精度控制
浮点数精度控制
# 方法1:% 格式化
pi = 3.141592653589793
# %f 默认保留6位小数
print("默认精度: %f" % pi) # 输出: 默认精度: 3.141593
# %.2f 保留2位小数
print("保留2位: %.2f" % pi) # 输出: 保留2位: 3.14
# %10.2f 总宽度10,保留2位小数,右对齐
print("宽度控制: %10.2f" % pi) # 输出: 宽度控制: 3.14
# %-10.2f 左对齐
print("左对齐: %-10.2f元" % pi) # 输出: 左对齐: 3.14 元
# 方法2:format() 方法
price = 1234.5678
# {:.2f} 保留2位小数
print("价格: {:.2f}元".format(price)) # 输出: 价格: 1234.57元
# {:10.2f} 总宽度10,保留2位小数
print("对齐: {:10.2f}".format(price)) # 输出: 对齐: 1234.57
# {:0>10.2f} 用0填充,右对齐
print("填充0: {:0>10.2f}".format(price)) # 输出: 填充0: 0001234.57
# {:<10.2f} 左对齐
print("左对齐: {:<10.2f}".format(price)) # 输出: 左对齐: 1234.57
# {:^10.2f} 居中对齐
print("居中: {:^10.2f}".format(price)) # 输出: 居中: 1234.57
# {:,} 千位分隔符
print("分隔符: {:,.2f}".format(price)) # 输出: 分隔符: 1,234.57
# 方法3:f-string
score = 87.6543
# 基本精度控制
print(f"成绩: {score:.2f}分") # 输出: 成绩: 87.65分
# 百分比格式
ratio = 0.8765
print(f"完成率: {ratio:.2%}") # 输出: 完成率: 87.65%
# 科学计数法
big_num = 123456789.123
print(f"科学计数: {big_num:.2e}") # 输出: 科学计数: 1.23e+08
# 组合使用:宽度+精度+对齐
print(f"复杂格式: {score:>10.3f}") # 输出: 复杂格式: 87.654
整数格式化
num = 42
# 进制转换
print(f"十进制: {num:d}") # 输出: 十进制: 42
print(f"二进制: {num:b}") # 输出: 二进制: 101010
print(f"八进制: {num:o}") # 输出: 八进制: 52
print(f"十六进制: {num:x}") # 输出: 十六进制: 2a
print(f"十六进制(大写): {num:X}") # 输出: 十六进制(大写): 2A
# 带前缀的进制表示
print(f"二进制带前缀: {num:#b}") # 输出: 二进制带前缀: 0b101010
print(f"十六进制带前缀: {num:#x}") # 输出: 十六进制带前缀: 0x2a
# 补零和对齐=
order_id = 7
print(f"订单号: {order_id:0>5d}") # 输出: 订单号: 00007
# 千位分隔符(适合大数字)
population = 1400000000
print(f"人口: {population:,}") # 输出: 人口: 1,400,000,000
格式化规范表:
| 格式符号 | 含义 | 示例 | 输出 |
|---|---|---|---|
:.2f |
保留2位小数 | f"{3.14159:.2f}" |
3.14 |
:10.2f |
宽度10,保留2位小数 | f"{3.14:10.2f}" |
3.14 |
:<10 |
左对齐,宽度10 | f"{'hi':<10}" |
hi |
:>10 |
右对齐,宽度10 | f"{'hi':>10}" |
hi |
:^10 |
居中,宽度10 | f"{'hi':^10}" |
hi |
:0>5 |
用0填充,宽度5 | f"{42:0>5}" |
00042 |
:, |
千位分隔符 | f"{1234567:,}" |
1,234,567 |
:.2% |
百分比,保留2位 | f"{0.875:.2%}" |
87.50% |
:.2e |
科学计数法 | f"{1234:.2e}" |
1.23e+03 |
:#x |
十六进制带前缀 | f"{255:#x}" |
0xff |
表达式的格式化
表达式格式化让字符串不再是静态的文本,而是可以包含动态计算的数据。类似于嵌入了一个微型计算器,随时可以进行运算。
#基础算术表达式
a = 10
b = 3
print(f"{a} + {b} = {a + b}") # 输出: 10 + 3 = 13
print(f"{a} - {b} = {a - b}") # 输出: 10 - 3 = 7
print(f"{a} * {b} = {a * b}") # 输出: 10 * 3 = 30
print(f"{a} / {b} = {a / b:.2f}") # 输出: 10 / 3 = 3.33
print(f"{a} // {b} = {a // b}") # 输出: 10 // 3 = 3
print(f"{a} % {b} = {a % b}") # 输出: 10 % 3 = 1
print(f"{a} ** {b} = {a ** b}") # 输出: 10 ** 3 = 1000
# 条件表达式(三元运算符)
age = 17
status = f"你{'已成年' if age >= 18 else '未成年'}"
print(status) # 输出: 你未成年
score = 85
grade = f"等级: {'优秀' if score >= 90 else '良好' if score >= 80 else '及格' if score >= 60 else '不及格'}"
print(grade) # 输出: 等级: 良好
# 函数调用
name = " alice "
print(f"原始: '{name}'") # 输出: 原始: ' alice '
print(f"去空格: '{name.strip()}'") # 输出: 去空格: 'alice'
print(f"大写: '{name.strip().upper()}'") # 输出: 大写: 'ALICE'
print(f"首字母大写: '{name.strip().title()}'") # 输出: 首字母大写: 'Alice'
# 使用内置函数
numbers = [1, 2, 3, 4, 5]
print(f"列表: {numbers}") # 输出: 列表: [1, 2, 3, 4, 5]
print(f"长度: {len(numbers)}") # 输出: 长度: 5
print(f"总和: {sum(numbers)}") # 输出: 总和: 15
print(f"最大值: {max(numbers)}") # 输出: 最大值: 5
print(f"平均值: {sum(numbers)/len(numbers):.2f}") # 输出: 平均值: 3.00
十、数据输入
input()函数的基础用法
# ============ 基本输入 ============
# input()总是返回字符串类型
name = input("请输入你的名字: ")
print(f"你好,{name}!")
# 输入提示可以包含任何文本
age = input("请输入你的年龄: ")
print(f"你输入的年龄是: {age},类型是: {type(age)}") # 类型是 <class 'str'>
# ============ 类型转换:将字符串转为数字 ============
# 转换为整数
age_str = input("请输入你的年龄: ")
age_int = int(age_str) # 字符串转整数
print(f"明年你将{age_int + 1}岁")
# 转换为浮点数
height_str = input("请输入你的身高(米): ")
height_float = float(height_str)
print(f"你的身高是{height_float}米,即{height_float * 100}厘米")
# 简化写法:直接在input外层转换
weight = float(input("请输入你的体重(kg): "))
bmi = weight / (height_float ** 2)
print(f"你的BMI指数是: {bmi:.2f}")
# ============ 输入多个值 ============
# 方法1:分别输入
print("请输入两个数字:")
num1 = int(input("第一个数: "))
num2 = int(input("第二个数: "))
print(f"{num1} + {num2} = {num1 + num2}")
# 方法2:一行输入,用空格分隔
print("请输入两个数字(用空格分隔): ")
numbers = input().split() # split()默认按空格分割,返回列表
num1 = int(numbers[0])
num2 = int(numbers[1])
print(f"{num1} * {num2} = {num1 * num2}")
# 方法3:使用解包(更优雅)
print("请输入三个数字(用空格分隔): ")
a, b, c = input().split()
a, b, c = int(a), int(b), int(c)
print(f"三个数的和: {a + b + c}")
# 方法4:使用map()函数(最简洁)
print("请输入三个数字(用空格分隔): ")
x, y, z = map(int, input().split())
print(f"三个数的积: {x * y * z}")
十一、条件判断
if语句的基本结构
# 最简单的if语句
age = 20
if age >= 18:
print("你已经成年了")
print("可以独立做决定")
# 注意:Python用缩进来表示代码块,不是用大括号
# 缩进通常是4个空格(按Tab键)
# if语句的判断条件
score = 85
if score >= 60:
print("及格了!")
# 条件可以是任何返回布尔值的表达式
name = "张三"
if name == "张三":
print("找到张三了")
# 条件可以是变量本身
has_ticket = True
if has_ticket:
print("可以进场")
# 空列表、空字符串、0、None都会被当作False
items = []
if items:
print("有物品")
else:
print("没有物品") # 会执行这个
if-else语句
# if-else:二选一
age = 16
if age >= 18:
print("成年人,可以看这部电影")
else:
print("未成年,不能观看")
# 实际应用:判断奇偶数
number = 7
if number % 2 == 0:
print(f"{number}是偶数")
else:
print(f"{number}是奇数")
# 实际应用:登录验证
username = input("请输入用户名: ")
password = input("请输入密码: ")
if username == "admin" and password == "123456":
print("登录成功!")
else:
print("用户名或密码错误")
# 可以在条件中使用复杂表达式
temperature = 28
humidity = 70
if temperature > 30 and humidity > 80:
print("又热又潮湿,开空调吧")
else:
print("天气还不错")
if-elif-else语句
# elif:多个条件判断(相当于else if)
score = 85
if score >= 90:
print("优秀")
elif score >= 80:
print("良好")
elif score >= 70:
print("中等")
elif score >= 60:
print("及格")
else:
print("不及格")
# 实际应用:根据时间问候
hour = 14
if hour < 6:
print("凌晨好,夜猫子")
elif hour < 9:
print("早上好")
elif hour < 12:
print("上午好")
elif hour < 14:
print("中午好")
elif hour < 18:
print("下午好")
elif hour < 22:
print("晚上好")
else:
print("夜深了,该休息了")
# 实际应用:BMI计算
weight = 70 # kg
height = 1.75 # m
bmi = weight / (height ** 2)
if bmi < 18.5:
print(f"BMI: {bmi:.1f} - 偏瘦")
elif bmi < 24:
print(f"BMI: {bmi:.1f} - 正常")
elif bmi < 28:
print(f"BMI: {bmi:.1f} - 偏胖")
else:
print(f"BMI: {bmi:.1f} - 肥胖")
嵌套if语句
# if语句可以嵌套使用
age = 20
has_ticket = True
has_id = True
if age >= 18:
print("年龄符合要求")
if has_ticket:
print("有票")
if has_id:
print("有身份证")
print("可以入场!")
else:
print("请出示身份证")
else:
print("请先购票")
else:
print("未成年不能入场")
# 实际应用:用户权限检查
is_logged_in = True
is_admin = False
is_vip = True
if is_logged_in:
print("已登录")
if is_admin:
print("管理员权限:可以访问所有功能")
elif is_vip:
print("VIP用户:可以访问高级功能")
else:
print("普通用户:可以访问基础功能")
else:
print("请先登录")
# 嵌套太深不好,可以用逻辑运算符简化
if is_logged_in and is_admin:
print("管理员已登录")
elif is_logged_in and is_vip:
print("VIP用户已登录")
elif is_logged_in:
print("普通用户已登录")
else:
print("未登录")
条件表达式(三元运算符)
# Python的三元运算符:value_if_true if condition else value_if_false
age = 20
status = "成年" if age >= 18 else "未成年"
print(status) # 成年
# 等价于:
if age >= 18:
status = "成年"
else:
status = "未成年"
# 实际应用:取绝对值
number = -5
abs_value = number if number >= 0 else -number
print(abs_value) # 5
# 实际应用:设置默认值
username = input("请输入用户名(直接回车使用默认): ")
username = username if username else "游客"
print(f"欢迎,{username}")
# 可以嵌套使用(但不要太复杂)
score = 85
grade = "优秀" if score >= 90 else "良好" if score >= 80 else "及格" if score >= 60 else "不及格"
print(grade) # 良好
条件判断的常见技巧
# 1. 判断是否在范围内
age = 25
if 18 <= age <= 65:
print("工作年龄段")
# 2. 判断是否在列表中
fruit = "苹果"
fruits = ["苹果", "香蕉", "橙子"]
if fruit in fruits:
print(f"{fruit}在列表中")
# 3. 判断字符串是否为空
name = ""
if not name: # 空字符串是False
print("名字不能为空")
# 4. 判断多个条件中的任意一个
day = "周六"
if day in ["周六", "周日"]:
print("周末,休息")
# 5. 使用any()和all()
scores = [85, 90, 78, 92]
if all(score >= 60 for score in scores):
print("所有科目都及格")
if any(score >= 90 for score in scores):
print("至少有一门优秀")
# 6. 避免重复判断
# 不好的写法
x = 10
if x > 5:
if x < 15:
print("x在5到15之间")
# 好的写法
if 5 < x < 15:
print("x在5到15之间")
条件判断的常见错误
# 错误1:使用=而不是==
x = 5
# if x = 5: # 语法错误!= 是赋值,== 是比较
if x == 5: # 正确
print("x等于5")
# 错误2:忘记冒号
# if x > 0 # 语法错误!缺少冒号
if x > 0: # 正确
print("x是正数")
# 错误3:缩进错误
if x > 0:
print("这行正确缩进")
# print("这行没有缩进,不属于if块")
# 错误4:比较浮点数相等
a = 0.1 + 0.2
# if a == 0.3: # 可能不成立,因为浮点数精度问题
if abs(a - 0.3) < 0.0001: # 正确做法
print("a约等于0.3")
# 错误5:混淆and和or
age = 25
# if age > 18 or age < 65: # 错误!这个条件永远为真
if age > 18 and age < 65: # 正确
print("工作年龄")
十二、循环语句
循环就像是让计算机重复做某件事,直到满足某个条件为止。Python有两种主要的循环:for循环和while循环。
for循环的基本用法
# 最基本的for循环:遍历列表
fruits = ["苹果", "香蕉", "橙子"]
for fruit in fruits:
print(fruit)
# 输出:
# 苹果
# 香蕉
# 橙子
# 遍历字符串(字符串也是可迭代对象)
for char in "Python":
print(char)
# 输出:P y t h o n(每个字母一行)
# 遍历字典
student = {"name": "张三", "age": 18, "grade": "高三"}
# 遍历键
for key in student:
print(key)
# 输出:name age grade
# 遍历值
for value in student.values():
print(value)
# 输出:张三 18 高三
# 同时遍历键和值
for key, value in student.items():
print(f"{key}: {value}")
# 输出:
# name: 张三
# age: 18
# grade: 高三
# 遍历集合
numbers = {1, 2, 3, 4, 5}
for num in numbers:
print(num)
range()函数
# range()生成数字序列,常用于for循环
# range(stop):从0到stop-1
for i in range(5):
print(i)
# 输出:0 1 2 3 4
# range(start, stop):从start到stop-1
for i in range(1, 6):
print(i)
# 输出:1 2 3 4 5
# range(start, stop, step):指定步长
for i in range(0, 10, 2):
print(i)
# 输出:0 2 4 6 8
# 倒序
for i in range(10, 0, -1):
print(i)
# 输出:10 9 8 7 6 5 4 3 2 1
# 实际应用:打印乘法表
for i in range(1, 10):
for j in range(1, i + 1):
print(f"{j}×{i}={i*j}", end="\t")
print() # 换行
# 实际应用:计算1到100的和
total = 0
for i in range(1, 101):
total += i
print(f"1到100的和是: {total}") # 5050
# 实际应用:找出1到100的所有偶数
evens = []
for i in range(1, 101):
if i % 2 == 0:
evens.append(i)
print(f"偶数有: {evens}")
enumerate()函数
# enumerate()可以同时获取索引和值
fruits = ["苹果", "香蕉", "橙子"]
# 不使用enumerate
for i in range(len(fruits)):
print(f"{i}: {fruits[i]}")
# 使用enumerate(更优雅)
for index, fruit in enumerate(fruits):
print(f"{index}: {fruit}")
# 输出:
# 0: 苹果
# 1: 香蕉
# 2: 橙子
# 指定起始索引
for index, fruit in enumerate(fruits, start=1):
print(f"{index}. {fruit}")
# 输出:
# 1. 苹果
# 2. 香蕉
# 3. 橙子
# 实际应用:给列表元素编号
students = ["张三", "李四", "王五"]
for num, name in enumerate(students, start=1):
print(f"学号{num}: {name}")
zip()函数
# zip()可以同时遍历多个序列
names = ["张三", "李四", "王五"]
ages = [18, 19, 20]
grades = ["高一", "高二", "高三"]
for name, age, grade in zip(names, ages, grades):
print(f"{name},{age}岁,{grade}")
# 输出:
# 张三,18岁,高一
# 李四,19岁,高二
# 王五,20岁,高三
# 长度不同时,以最短的为准
list1 = [1, 2, 3, 4, 5]
list2 = ['a', 'b', 'c']
for num, letter in zip(list1, list2):
print(f"{num}-{letter}")
# 输出:
# 1-a
# 2-b
# 3-c
# 实际应用:创建字典
keys = ["name", "age", "city"]
values = ["张三", 25, "北京"]
person = dict(zip(keys, values))
print(person) # {'name': '张三', 'age': 25, 'city': '北京'}
while循环
# while循环:只要条件为真就一直执行
count = 0
while count < 5:
print(f"count = {count}")
count += 1
# 输出:count = 0 到 count = 4
# 实际应用:猜数字游戏
import random
secret = random.randint(1, 100)
guess = 0
attempts = 0
while guess != secret:
guess = int(input("猜一个1到100的数字: "))
attempts += 1
if guess < secret:
print("太小了")
elif guess > secret:
print("太大了")
else:
print(f"恭喜你猜对了!用了{attempts}次")
# 实际应用:输入验证
password = ""
while len(password) < 6:
password = input("请输入密码(至少6位): ")
if len(password) < 6:
print("密码太短,请重新输入")
print("密码设置成功")
# 实际应用:菜单循环
while True:
print("\n=== 菜单 ===")
print("1. 查看信息")
print("2. 修改信息")
print("3. 退出")
choice = input("请选择: ")
if choice == "1":
print("查看信息...")
elif choice == "2":
print("修改信息...")
elif choice == "3":
print("再见!")
break # 跳出循环
else:
print("无效选择,请重新输入")
break和continue
# break:立即跳出循环
for i in range(10):
if i == 5:
break # 遇到5就停止
print(i)
# 输出:0 1 2 3 4
# continue:跳过本次循环,继续下一次
for i in range(10):
if i % 2 == 0:
continue # 跳过偶数
print(i)
# 输出:1 3 5 7 9
# 实际应用:查找第一个符合条件的元素
numbers = [1, 3, 5, 8, 10, 12]
for num in numbers:
if num % 2 == 0:
print(f"找到第一个偶数: {num}")
break
# 实际应用:跳过特定条件
scores = [85, -1, 90, -1, 78, 92] # -1表示缺考
total = 0
count = 0
for score in scores:
if score == -1:
continue # 跳过缺考
total += score
count += 1
average = total / count
print(f"平均分: {average:.2f}")
# break和continue在while循环中
count = 0
while True:
count += 1
if count % 2 == 0:
continue # 跳过偶数
print(count)
if count >= 10:
break # 到10就停止
else子句
# for和while循环都可以有else子句
# 正常结束循环时执行else,被break打断则不执行
# 示例1:查找元素
numbers = [1, 3, 5, 7, 9]
target = 6
for num in numbers:
if num == target:
print(f"找到了{target}")
break
else:
print(f"没找到{target}") # 会执行这个
# 示例2:验证所有元素
scores = [85, 90, 78, 92, 88]
for score in scores:
if score < 60:
print("有人不及格")
break
else:
print("全部及格") # 会执行这个
# while循环的else
count = 0
while count < 5:
print(count)
count += 1
else:
print("循环正常结束") # 会执行
# 被break打断的情况
count = 0
while count < 10:
if count == 5:
break
count += 1
else:
print("这不会执行") # 不会执行
嵌套循环
# 循环可以嵌套使用
# 打印矩形
for i in range(3):
for j in range(5):
print("*", end="")
print() # 换行
# 输出:
# *****
# *****
# *****
# 打印三角形
for i in range(1, 6):
for j in range(i):
print("*", end="")
print()
# 输出:
# *
# **
# ***
# ****
# *****
# 实际应用:遍历二维列表
matrix = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
]
for row in matrix:
for num in row:
print(num, end=" ")
print()
# 实际应用:找出所有两位数中能被7整除的数
for i in range(10, 100):
if i % 7 == 0:
print(i, end=" ")
print()
# 实际应用:生成所有两位数的组合
for i in range(1, 10):
for j in range(0, 10):
print(f"{i}{j}", end=" ")
print()
列表推导式
# 列表推导式:用一行代码创建列表
# 基本语法:[expression for item in iterable]
# 传统方法
squares = []
for i in range(10):
squares.append(i ** 2)
print(squares)
# 列表推导式(更简洁)
squares = [i ** 2 for i in range(10)]
print(squares) # [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
# 带条件的列表推导式
# [expression for item in iterable if condition]
evens = [i for i in range(20) if i % 2 == 0]
print(evens) # [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
# 实际应用:提取字符串中的数字
text = "abc123def456"
digits = [char for char in text if char.isdigit()]
print(digits) # ['1', '2', '3', '4', '5', '6']
# 实际应用:转换列表元素
names = ["alice", "bob", "charlie"]
upper_names = [name.upper() for name in names]
print(upper_names) # ['ALICE', 'BOB', 'CHARLIE']
# 嵌套列表推导式
matrix = [[i * j for j in range(1, 4)] for i in range(1, 4)]
print(matrix) # [[1, 2, 3], [2, 4, 6], [3, 6, 9]]
# 字典推导式
squares_dict = {i: i ** 2 for i in range(5)}
print(squares_dict) # {0: 0, 1: 1, 2: 4, 3: 9, 4: 16}
# 集合推导式
unique_chars = {char.lower() for char in "Hello World"}
print(unique_chars) # {'h', 'e', 'l', 'o', 'w', 'r', 'd', ' '}
循环的性能优化技巧
# 1. 避免在循环中重复计算
# 不好的写法
total = 0
for i in range(1000):
total += len([1, 2, 3, 4, 5]) # 每次都计算长度
# 好的写法
total = 0
length = len([1, 2, 3, 4, 5]) # 只计算一次
for i in range(1000):
total += length
# 2. 使用生成器表达式节省内存
# 列表推导式(占用内存)
squares = [i ** 2 for i in range(1000000)]
# 生成器表达式(节省内存)
squares = (i ** 2 for i in range(1000000))
# 3. 使用内置函数
# 不好的写法
total = 0
for i in range(100):
total += i
# 好的写法
total = sum(range(100))
# 4. 避免不必要的循环
# 不好的写法
found = False
for item in items:
if item == target:
found = True
# 好的写法
found = target in items
十三、函数
函数就像是一个工具箱,把常用的代码打包起来,需要的时候直接调用。这样可以避免重复写代码,让程序更清晰、更容易维护。
函数的定义和调用
# 最简单的函数
def greet():
print("你好!")
# 调用函数
greet() # 输出:你好!
# 带参数的函数
def greet_person(name):
print(f"你好,{name}!")
greet_person("张三") # 输出:你好,张三!
greet_person("李四") # 输出:你好,李四!
# 多个参数
def add(a, b):
result = a + b
print(f"{a} + {b} = {result}")
add(3, 5) # 输出:3 + 5 = 8
add(10, 20) # 输出:10 + 20 = 30
# 带返回值的函数
def multiply(a, b):
return a * b
result = multiply(4, 5)
print(result) # 20
# 可以直接在表达式中使用
print(f"4乘以5等于{multiply(4, 5)}")
# 实际应用:计算圆的面积
def circle_area(radius):
pi = 3.14159
area = pi * radius ** 2
return area
area1 = circle_area(5)
area2 = circle_area(10)
print(f"半径5的圆面积: {area1:.2f}")
print(f"半径10的圆面积: {area2:.2f}")
参数的类型
# 1. 位置参数:按顺序传递
def introduce(name, age, city):
print(f"我叫{name},{age}岁,来自{city}")
introduce("张三", 25, "北京") # 必须按顺序
# 2. 关键字参数:指定参数名
introduce(name="李四", age=30, city="上海")
introduce(age=28, city="广州", name="王五") # 顺序可以变
# 3. 默认参数:有默认值的参数
def greet(name, greeting="你好"):
print(f"{greeting},{name}!")
greet("张三") # 使用默认值:你好,张三!
greet("李四", "早上好") # 自定义:早上好,李四!
# 默认参数必须放在后面
def make_coffee(size, sugar=1, milk=True):
print(f"制作{size}杯咖啡,糖{sugar}勺,{'加' if milk else '不加'}奶")
make_coffee("大") # 大杯咖啡,糖1勺,加奶
make_coffee("中", 2) # 中杯咖啡,糖2勺,加奶
make_coffee("小", 0, False) # 小杯咖啡,糖0勺,不加奶
# 4. 可变参数:*args(接收任意数量的位置参数)
def sum_all(*numbers):
total = 0
for num in numbers:
total += num
return total
print(sum_all(1, 2, 3)) # 6
print(sum_all(1, 2, 3, 4, 5)) # 15
print(sum_all(10, 20)) # 30
# 5. 关键字可变参数:**kwargs(接收任意数量的关键字参数)
def print_info(**info):
for key, value in info.items():
print(f"{key}: {value}")
print_info(name="张三", age=25, city="北京")
# 输出:
# name: 张三
# age: 25
# city: 北京
# 6. 混合使用(顺序:位置参数、*args、默认参数、**kwargs)
def complex_func(a, b, *args, c=10, **kwargs):
print(f"a={a}, b={b}")
print(f"args={args}")
print(f"c={c}")
print(f"kwargs={kwargs}")
complex_func(1, 2, 3, 4, 5, c=20, x=100, y=200)
# 输出:
# a=1, b=2
# args=(3, 4, 5)
# c=20
# kwargs={'x': 100, 'y': 200}
返回值
# 返回单个值
def square(x):
return x ** 2
result = square(5)
print(result) # 25
# 返回多个值(实际返回的是元组)
def get_user_info():
name = "张三"
age = 25
city = "北京"
return name, age, city
# 接收多个返回值
name, age, city = get_user_info()
print(f"{name}, {age}岁, {city}")
# 也可以作为元组接收
info = get_user_info()
print(info) # ('张三', 25, '北京')
# 没有return语句,默认返回None
def no_return():
print("这个函数没有返回值")
result = no_return()
print(result) # None
# 提前返回
def check_age(age):
if age < 0:
return "年龄不能为负数"
if age < 18:
return "未成年"
if age < 60:
return "成年"
return "老年"
print(check_age(15)) # 未成年
print(check_age(30)) # 成年
print(check_age(-5)) # 年龄不能为负数
# 实际应用:计算成绩等级
def get_grade(score):
if score < 0 or score > 100:
return "无效分数"
if score >= 90:
return "A"
if score >= 80:
return "B"
if score >= 70:
return "C"
if score >= 60:
return "D"
return "F"
print(get_grade(95)) # A
print(get_grade(75)) # C
print(get_grade(55)) # F
变量作用域
# 全局变量:在函数外定义
global_var = "我是全局变量"
def test_scope():
# 局部变量:在函数内定义
local_var = "我是局部变量"
print(global_var) # 可以访问全局变量
print(local_var)
test_scope()
# print(local_var) # 错误!函数外无法访问局部变量
# 修改全局变量需要使用global关键字
count = 0
def increment():
global count # 声明要修改全局变量
count += 1
print(f"count = {count}")
increment() # count = 1
increment() # count = 2
print(count) # 2
# 不使用global会创建新的局部变量
score = 100
def change_score():
score = 200 # 这是新的局部变量,不影响全局的score
print(f"函数内: {score}")
change_score() # 函数内: 200
print(f"函数外: {score}") # 函数外: 100
# 嵌套函数的作用域
def outer():
x = "outer"
def inner():
nonlocal x # 修改外层函数的变量
x = "inner"
print(f"inner函数: {x}")
print(f"调用inner前: {x}")
inner()
print(f"调用inner后: {x}")
outer()
# 输出:
# 调用inner前: outer
# inner函数: inner
# 调用inner后: inner
Lambda函数(匿名函数)
# 普通函数
def square(x):
return x ** 2
# Lambda函数(一行搞定)
square_lambda = lambda x: x ** 2
print(square(5)) # 25
print(square_lambda(5)) # 25
# Lambda函数常用于简单操作
add = lambda a, b: a + b
print(add(3, 5)) # 8
# 实际应用:排序
students = [
{"name": "张三", "score": 85},
{"name": "李四", "score": 92},
{"name": "王五", "score": 78}
]
# 按分数排序
students.sort(key=lambda s: s["score"])
print(students)
# [{'name': '王五', 'score': 78}, {'name': '张三', 'score': 85}, {'name': '李四', 'score': 92}]
# 按名字排序
students.sort(key=lambda s: s["name"])
print(students)
# 实际应用:过滤列表
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
evens = list(filter(lambda x: x % 2 == 0, numbers))
print(evens) # [2, 4, 6, 8, 10]
# 实际应用:映射列表
squares = list(map(lambda x: x ** 2, numbers))
print(squares) # [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
# Lambda函数的限制:只能写一个表达式,不能包含复杂逻辑
# 复杂逻辑还是用普通函数
递归函数
# 递归:函数调用自己
# 经典例子:计算阶乘
def factorial(n):
if n == 0 or n == 1:
return 1 # 基准情况
else:
return n * factorial(n - 1) # 递归调用
print(factorial(5)) # 5! = 5×4×3×2×1 = 120
print(factorial(10)) # 3628800
# 经典例子:斐波那契数列
def fibonacci(n):
if n <= 1:
return n
else:
return fibonacci(n - 1) + fibonacci(n - 2)
# 打印前10个斐波那契数
for i in range(10):
print(fibonacci(i), end=" ")
print() # 0 1 1 2 3 5 8 13 21 34
# 实际应用:计算幂
def power(base, exp):
if exp == 0:
return 1
else:
return base * power(base, exp - 1)
print(power(2, 5)) # 2^5 = 32
# 实际应用:遍历嵌套列表
def flatten(nested_list):
result = []
for item in nested_list:
if isinstance(item, list):
result.extend(flatten(item)) # 递归处理子列表
else:
result.append(item)
return result
nested = [1, [2, 3], [4, [5, 6]], 7]
flat = flatten(nested)
print(flat) # [1, 2, 3, 4, 5, 6, 7]
# 注意:递归深度有限制,太深会报错
# import sys
# print(sys.getrecursionlimit()) # 默认1000
文档字符串(Docstring)
# 函数的说明文档,用三引号
def calculate_bmi(weight, height):
"""
计算BMI指数
参数:
weight (float): 体重,单位kg
height (float): 身高,单位m
返回:
float: BMI指数
示例:
>>> calculate_bmi(70, 1.75)
22.86
"""
bmi = weight / (height ** 2)
return round(bmi, 2)
# 查看文档
print(calculate_bmi.__doc__)
# 使用help()查看
help(calculate_bmi)
# 实际应用:完整的函数文档
def process_data(data, method="average", ignore_negative=True):
"""
处理数据列表
这个函数可以对数据列表进行各种统计处理。
参数:
data (list): 数字列表
method (str): 处理方法,可选 'average', 'sum', 'max', 'min'
ignore_negative (bool): 是否忽略负数
返回:
float: 处理结果
异常:
ValueError: 如果data为空或method无效
示例:
>>> process_data([1, 2, 3, 4, 5])
3.0
>>> process_data([1, -2, 3, -4, 5], ignore_negative=False)
0.6
"""
if not data:
raise ValueError("数据列表不能为空")
if ignore_negative:
data = [x for x in data if x >= 0]
if method == "average":
return sum(data) / len(data)
elif method == "sum":
return sum(data)
elif method == "max":
return max(data)
elif method == "min":
return min(data)
else:
raise ValueError(f"无效的方法: {method}")
函数的高级特性
# 1. 函数作为参数传递
def apply_operation(x, y, operation):
return operation(x, y)
def add(a, b):
return a + b
def multiply(a, b):
return a * b
print(apply_operation(5, 3, add)) # 8
print(apply_operation(5, 3, multiply)) # 15
# 2. 函数作为返回值
def make_multiplier(n):
def multiplier(x):
return x * n
return multiplier
times_3 = make_multiplier(3)
times_5 = make_multiplier(5)
print(times_3(10)) # 30
print(times_5(10)) # 50
# 3. 闭包
def counter():
count = 0
def increment():
nonlocal count
count += 1
return count
return increment
c1 = counter()
print(c1()) # 1
print(c1()) # 2
print(c1()) # 3
c2 = counter()
print(c2()) # 1(新的计数器)
# 4. 装饰器(高级话题,简单了解)
def timer_decorator(func):
import time
def wrapper(*args, **kwargs):
start = time.time()
result = func(*args, **kwargs)
end = time.time()
print(f"{func.__name__}执行时间: {end - start:.4f}秒")
return result
return wrapper
@timer_decorator
def slow_function():
import time
time.sleep(1)
print("函数执行完毕")
slow_function()
# 输出:
# 函数执行完毕
# slow_function执行时间: 1.0001秒
十四、数据结构详解
Python内置了几种强大的数据结构,每种都有丰富的方法和接口。掌握这些数据结构是写好Python代码的基础。
列表(List)的方法
# 创建列表
fruits = ["苹果", "香蕉", "橙子"]
numbers = [1, 2, 3, 4, 5]
mixed = [1, "hello", 3.14, True]
empty = []
# ========== 添加元素 ==========
# append():在末尾添加一个元素
fruits.append("葡萄")
print(fruits) # ['苹果', '香蕉', '橙子', '葡萄']
# insert():在指定位置插入元素
fruits.insert(1, "西瓜") # 在索引1的位置插入
print(fruits) # ['苹果', '西瓜', '香蕉', '橙子', '葡萄']
# extend():添加多个元素(合并列表)
fruits.extend(["芒果", "草莓"])
print(fruits) # ['苹果', '西瓜', '香蕉', '橙子', '葡萄', '芒果', '草莓']
# 注意append和extend的区别
list1 = [1, 2, 3]
list1.append([4, 5])
print(list1) # [1, 2, 3, [4, 5]](整个列表作为一个元素)
list2 = [1, 2, 3]
list2.extend([4, 5])
print(list2) # [1, 2, 3, 4, 5](逐个添加元素)
# ========== 删除元素 ==========
# remove():删除第一个匹配的元素
fruits = ["苹果", "香蕉", "橙子", "香蕉"]
fruits.remove("香蕉")
print(fruits) # ['苹果', '橙子', '香蕉'](只删除第一个)
# pop():删除并返回指定位置的元素(默认最后一个)
fruits = ["苹果", "香蕉", "橙子"]
last = fruits.pop()
print(last) # 橙子
print(fruits) # ['苹果', '香蕉']
first = fruits.pop(0)
print(first) # 苹果
print(fruits) # ['香蕉']
# del:删除指定位置或切片
fruits = ["苹果", "香蕉", "橙子", "葡萄", "西瓜"]
del fruits[1]
print(fruits) # ['苹果', '橙子', '葡萄', '西瓜']
del fruits[1:3]
print(fruits) # ['苹果', '西瓜']
# clear():清空列表
fruits.clear()
print(fruits) # []
# ========== 查找和统计 ==========
numbers = [1, 2, 3, 2, 4, 2, 5]
# index():查找元素的索引
idx = numbers.index(3)
print(idx) # 2
# 查找指定范围内的索引
idx = numbers.index(2, 2) # 从索引2开始查找
print(idx) # 3
# count():统计元素出现次数
count = numbers.count(2)
print(count) # 3
# in:检查元素是否存在
print(3 in numbers) # True
print(10 in numbers) # False
# ========== 排序和反转 ==========
numbers = [3, 1, 4, 1, 5, 9, 2, 6]
# sort():原地排序(修改原列表)
numbers.sort()
print(numbers) # [1, 1, 2, 3, 4, 5, 6, 9]
# 降序排序
numbers.sort(reverse=True)
print(numbers) # [9, 6, 5, 4, 3, 2, 1, 1]
# sorted():返回新列表(不修改原列表)
numbers = [3, 1, 4, 1, 5]
sorted_numbers = sorted(numbers)
print(numbers) # [3, 1, 4, 1, 5](原列表不变)
print(sorted_numbers) # [1, 1, 3, 4, 5]
# 自定义排序
students = [
{"name": "张三", "score": 85},
{"name": "李四", "score": 92},
{"name": "王五", "score": 78}
]
students.sort(key=lambda s: s["score"], reverse=True)
print(students) # 按分数降序
# reverse():反转列表
numbers = [1, 2, 3, 4, 5]
numbers.reverse()
print(numbers) # [5, 4, 3, 2, 1]
# ========== 复制列表 ==========
# 浅拷贝
original = [1, 2, 3]
copy1 = original.copy()
copy2 = original[:]
copy3 = list(original)
copy1.append(4)
print(original) # [1, 2, 3](不受影响)
print(copy1) # [1, 2, 3, 4]
# 注意:浅拷贝对嵌套列表的影响
original = [[1, 2], [3, 4]]
copy = original.copy()
copy[0].append(3)
print(original) # [[1, 2, 3], [3, 4]](内层列表被修改)
print(copy) # [[1, 2, 3], [3, 4]]
# 深拷贝
import copy
original = [[1, 2], [3, 4]]
deep_copy = copy.deepcopy(original)
deep_copy[0].append(3)
print(original) # [[1, 2], [3, 4]](不受影响)
print(deep_copy) # [[1, 2, 3], [3, 4]]
# ========== 其他常用操作 ==========
# len():获取长度
fruits = ["苹果", "香蕉", "橙子"]
print(len(fruits)) # 3
# min()和max():最小值和最大值
numbers = [3, 1, 4, 1, 5, 9, 2, 6]
print(min(numbers)) # 1
print(max(numbers)) # 9
# sum():求和
print(sum(numbers)) # 31
# 列表拼接
list1 = [1, 2, 3]
list2 = [4, 5, 6]
combined = list1 + list2
print(combined) # [1, 2, 3, 4, 5, 6]
# 列表重复
repeated = [1, 2] * 3
print(repeated) # [1, 2, 1, 2, 1, 2]
# 列表切片赋值
numbers = [1, 2, 3, 4, 5]
numbers[1:4] = [20, 30]
print(numbers) # [1, 20, 30, 5]
元组(Tuple)的方法
# 创建元组
point = (3, 5)
person = ("张三", 25, "北京")
single = (5,) # 单元素元组要加逗号
empty = ()
# 元组是不可变的,但方法较少
numbers = (1, 2, 3, 2, 4, 2, 5)
# count():统计元素出现次数
print(numbers.count(2)) # 3
# index():查找元素索引
print(numbers.index(3)) # 2
# 元组的其他操作
# len():长度
print(len(numbers)) # 7
# in:检查元素
print(3 in numbers) # True
# 拼接
tuple1 = (1, 2, 3)
tuple2 = (4, 5, 6)
combined = tuple1 + tuple2
print(combined) # (1, 2, 3, 4, 5, 6)
# 重复
repeated = (1, 2) * 3
print(repeated) # (1, 2, 1, 2, 1, 2)
# 元组解包
point = (3, 5)
x, y = point
print(f"x={x}, y={y}") # x=3, y=5
# 交换变量
a, b = 10, 20
a, b = b, a
print(a, b) # 20 10
# 函数返回多个值(实际是元组)
def get_min_max(numbers):
return min(numbers), max(numbers)
minimum, maximum = get_min_max([1, 5, 3, 9, 2])
print(f"最小值: {minimum}, 最大值: {maximum}")
# 元组虽然不可变,但如果包含可变对象,可变对象可以修改
tuple_with_list = (1, 2, [3, 4])
tuple_with_list[2].append(5)
print(tuple_with_list) # (1, 2, [3, 4, 5])
# 命名元组(更清晰的元组)
from collections import namedtuple
Point = namedtuple('Point', ['x', 'y'])
p = Point(3, 5)
print(p.x, p.y) # 3 5
print(p[0], p[1]) # 3 5(也可以用索引)
Person = namedtuple('Person', ['name', 'age', 'city'])
person = Person('张三', 25, '北京')
print(person.name) # 张三
print(person.age) # 25
字典(Dictionary)的方法
# 创建字典
student = {
"name": "张三",
"age": 18,
"grade": "高三"
}
# 空字典
empty = {}
empty2 = dict()
# ========== 访问和修改 ==========
# 访问值
print(student["name"]) # 张三
# get():安全访问(不存在返回None或默认值)
print(student.get("name")) # 张三
print(student.get("score")) # None
print(student.get("score", 0)) # 0(默认值)
# 修改值
student["age"] = 19
print(student)
# 添加新键值对
student["score"] = 85
print(student)
# ========== 删除操作 ==========
# del:删除键值对
del student["grade"]
print(student)
# pop():删除并返回值
score = student.pop("score")
print(score) # 85
print(student)
# pop()带默认值
result = student.pop("nonexistent", "不存在")
print(result) # 不存在
# popitem():删除并返回最后一个键值对(Python 3.7+保证顺序)
student = {"name": "张三", "age": 18, "city": "北京"}
item = student.popitem()
print(item) # ('city', '北京')
print(student)
# clear():清空字典
student.clear()
print(student) # {}
# ========== 查询操作 ==========
student = {"name": "张三", "age": 18, "city": "北京"}
# keys():获取所有键
keys = student.keys()
print(keys) # dict_keys(['name', 'age', 'city'])
print(list(keys)) # ['name', 'age', 'city']
# values():获取所有值
values = student.values()
print(list(values)) # ['张三', 18, '北京']
# items():获取所有键值对
items = student.items()
print(list(items)) # [('name', '张三'), ('age', 18), ('city', '北京')]
# 遍历字典
for key in student:
print(f"{key}: {student[key]}")
for key, value in student.items():
print(f"{key}: {value}")
# in:检查键是否存在
print("name" in student) # True
print("score" in student) # False
# ========== 更新操作 ==========
# update():更新字典
student = {"name": "张三", "age": 18}
student.update({"age": 19, "city": "北京"})
print(student) # {'name': '张三', 'age': 19, 'city': '北京'}
# 也可以用关键字参数
student.update(score=85, grade="高三")
print(student)
# setdefault():如果键不存在则设置默认值
student.setdefault("hobby", "篮球")
print(student) # 添加了hobby
student.setdefault("name", "李四") # name已存在,不修改
print(student["name"]) # 还是张三
# ========== 字典推导式 ==========
# 创建字典
squares = {x: x**2 for x in range(5)}
print(squares) # {0: 0, 1: 1, 2: 4, 3: 9, 4: 16}
# 过滤字典
student_scores = {"张三": 85, "李四": 92, "王五": 78, "赵六": 88}
high_scores = {name: score for name, score in student_scores.items() if score >= 85}
print(high_scores) # {'张三': 85, '李四': 92, '赵六': 88}
# 交换键值
original = {"a": 1, "b": 2, "c": 3}
swapped = {value: key for key, value in original.items()}
print(swapped) # {1: 'a', 2: 'b', 3: 'c'}
# ========== 嵌套字典 ==========
students = {
"001": {"name": "张三", "age": 18, "score": 85},
"002": {"name": "李四", "age": 19, "score": 92},
"003": {"name": "王五", "age": 18, "score": 78}
}
# 访问嵌套值
print(students["001"]["name"]) # 张三
# 遍历嵌套字典
for student_id, info in students.items():
print(f"学号: {student_id}")
for key, value in info.items():
print(f" {key}: {value}")
# ========== 字典的其他技巧 ==========
# 合并字典(Python 3.9+)
dict1 = {"a": 1, "b": 2}
dict2 = {"c": 3, "d": 4}
merged = dict1 | dict2
print(merged) # {'a': 1, 'b': 2, 'c': 3, 'd': 4}
# 旧版本的合并方法
merged = {**dict1, **dict2}
print(merged)
# 从两个列表创建字典
keys = ["name", "age", "city"]
values = ["张三", 25, "北京"]
person = dict(zip(keys, values))
print(person) # {'name': '张三', 'age': 25, 'city': '北京'}
# defaultdict:带默认值的字典
from collections import defaultdict
# 统计单词出现次数
word_count = defaultdict(int) # 默认值为0
words = ["apple", "banana", "apple", "orange", "banana", "apple"]
for word in words:
word_count[word] += 1
print(dict(word_count)) # {'apple': 3, 'banana': 2, 'orange': 1}
# Counter:专门用于计数
from collections import Counter
words = ["apple", "banana", "apple", "orange", "banana", "apple"]
counter = Counter(words)
print(counter) # Counter({'apple': 3, 'banana': 2, 'orange': 1})
print(counter.most_common(2)) # [('apple', 3), ('banana', 2)]
集合(Set)的方法
# 创建集合
fruits = {"苹果", "香蕉", "橙子"}
numbers = {1, 2, 3, 4, 5}
empty = set() # 注意:{}是空字典,不是空集合
# 集合自动去重
numbers = {1, 2, 2, 3, 3, 3, 4}
print(numbers) # {1, 2, 3, 4}
# ========== 添加和删除 ==========
# add():添加单个元素
fruits = {"苹果", "香蕉"}
fruits.add("橙子")
print(fruits) # {'苹果', '香蕉', '橙子'}
# update():添加多个元素
fruits.update(["葡萄", "西瓜"])
print(fruits)
# remove():删除元素(不存在会报错)
fruits.remove("香蕉")
print(fruits)
# discard():删除元素(不存在不报错)
fruits.discard("芒果") # 不存在,但不报错
print(fruits)
# pop():随机删除并返回一个元素
item = fruits.pop()
print(f"删除了: {item}")
print(fruits)
# clear():清空集合
fruits.clear()
print(fruits) # set()
# ========== 集合运算 ==========
set1 = {1, 2, 3, 4, 5}
set2 = {4, 5, 6, 7, 8}
# 并集(所有元素)
union = set1 | set2
print(union) # {1, 2, 3, 4, 5, 6, 7, 8}
print(set1.union(set2)) # 同上
# 交集(共同元素)
intersection = set1 & set2
print(intersection) # {4, 5}
print(set1.intersection(set2)) # 同上
# 差集(在set1但不在set2)
difference = set1 - set2
print(difference) # {1, 2, 3}
print(set1.difference(set2)) # 同上
# 对称差集(不同时在两个集合中的元素)
sym_diff = set1 ^ set2
print(sym_diff) # {1, 2, 3, 6, 7, 8}
print(set1.symmetric_difference(set2)) # 同上
# ========== 集合关系 ==========
set_a = {1, 2, 3}
set_b = {1, 2, 3, 4, 5}
set_c = {6, 7, 8}
# 子集
print(set_a.issubset(set_b)) # True(set_a是set_b的子集)
print(set_a <= set_b) # True
# 超集
print(set_b.issuperset(set_a)) # True(set_b是set_a的超集)
print(set_b >= set_a) # True
# 不相交(没有共同元素)
print(set_a.isdisjoint(set_c)) # True(没有共同元素)
print(set_a.isdisjoint(set_b)) # False(有共同元素)
# ========== 集合推导式 ==========
# 创建集合
squares = {x**2 for x in range(10)}
print(squares) # {0, 1, 4, 9, 16, 25, 36, 49, 64, 81}
# 过滤集合
numbers = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
evens = {x for x in numbers if x % 2 == 0}
print(evens) # {2, 4, 6, 8, 10}
# ========== 集合的实际应用 ==========
# 1. 去重
numbers = [1, 2, 2, 3, 3, 3, 4, 4, 4, 4]
unique = list(set(numbers))
print(unique) # [1, 2, 3, 4]
# 2. 查找共同好友
user1_friends = {"张三", "李四", "王五", "赵六"}
user2_friends = {"李四", "王五", "孙七", "周八"}
common_friends = user1_friends & user2_friends
print(f"共同好友: {common_friends}") # {'李四', '王五'}
# 3. 查找独有好友
only_user1 = user1_friends - user2_friends
print(f"只有用户1有的好友: {only_user1}") # {'张三', '赵六'}
# 4. 检查权限
user_permissions = {"read", "write", "delete"}
required_permissions = {"read", "write"}
has_permission = required_permissions.issubset(user_permissions)
print(f"有权限: {has_permission}") # True
# 5. 统计不同的字符
text = "hello world"
unique_chars = set(text)
print(f"不同的字符: {unique_chars}")
print(f"字符种类数: {len(unique_chars)}")
# 6. 快速成员检查(集合比列表快得多)
# 列表检查:O(n)
large_list = list(range(1000000))
print(999999 in large_list) # 慢
# 集合检查:O(1)
large_set = set(range(1000000))
print(999999 in large_set) # 快
# ========== frozenset(不可变集合)==========
# frozenset是不可变的集合,可以作为字典的键
immutable_set = frozenset([1, 2, 3, 4, 5])
print(immutable_set) # frozenset({1, 2, 3, 4, 5})
# 不能修改
# immutable_set.add(6) # 报错!AttributeError
# 可以作为字典的键
set_dict = {
frozenset([1, 2]): "集合1",
frozenset([3, 4]): "集合2"
}
print(set_dict[frozenset([1, 2])]) # 集合1
# frozenset支持集合运算
fs1 = frozenset([1, 2, 3])
fs2 = frozenset([3, 4, 5])
print(fs1 | fs2) # frozenset({1, 2, 3, 4, 5})
print(fs1 & fs2) # frozenset({3})
字符串(String)的高级方法
# ========== 大小写转换 ==========
text = "Hello World"
# upper():全部大写
print(text.upper()) # HELLO WORLD
# lower():全部小写
print(text.lower()) # hello world
# capitalize():首字母大写,其余小写
print(text.capitalize()) # Hello world
# title():每个单词首字母大写
print(text.title()) # Hello World
# swapcase():大小写互换
print(text.swapcase()) # hELLO wORLD
# casefold():更激进的小写(处理特殊字符)
german = "ß"
print(german.lower()) # ß
print(german.casefold()) # ss
# ========== 查找和替换 ==========
text = "Python is awesome. Python is powerful."
# find():查找子串位置(找不到返回-1)
pos = text.find("Python")
print(pos) # 0
pos = text.find("Python", 10) # 从位置10开始查找
print(pos) # 19
pos = text.find("Java")
print(pos) # -1(找不到)
# rfind():从右边开始查找
pos = text.rfind("Python")
print(pos) # 19
# index():查找子串位置(找不到会报错)
pos = text.index("Python")
print(pos) # 0
# pos = text.index("Java") # 报错!ValueError
# count():统计子串出现次数
count = text.count("Python")
print(count) # 2
# replace():替换子串
new_text = text.replace("Python", "Java")
print(new_text) # Java is awesome. Java is powerful.
# 限制替换次数
new_text = text.replace("Python", "Java", 1)
print(new_text) # Java is awesome. Python is powerful.
# ========== 分割和连接 ==========
# split():分割字符串(返回列表)
text = "apple,banana,orange"
fruits = text.split(",")
print(fruits) # ['apple', 'banana', 'orange']
# 默认按空格分割
text = "Hello World Python"
words = text.split()
print(words) # ['Hello', 'World', 'Python']
# 限制分割次数
text = "a-b-c-d-e"
parts = text.split("-", 2)
print(parts) # ['a', 'b', 'c-d-e']
# rsplit():从右边开始分割
parts = text.rsplit("-", 2)
print(parts) # ['a-b-c', 'd', 'e']
# splitlines():按行分割
text = "第一行\n第二行\n第三行"
lines = text.splitlines()
print(lines) # ['第一行', '第二行', '第三行']
# join():连接字符串
words = ["Hello", "World", "Python"]
sentence = " ".join(words)
print(sentence) # Hello World Python
# 用不同的分隔符
csv = ",".join(words)
print(csv) # Hello,World,Python
# ========== 去除空白 ==========
text = " Hello World "
# strip():去除两端空白
print(text.strip()) # "Hello World"
# lstrip():去除左边空白
print(text.lstrip()) # "Hello World "
# rstrip():去除右边空白
print(text.rstrip()) # " Hello World"
# 去除指定字符
text = "***Hello***"
print(text.strip("*")) # "Hello"
# ========== 判断方法 ==========
# startswith():是否以指定字符串开头
text = "Python is great"
print(text.startswith("Python")) # True
print(text.startswith("Java")) # False
# 可以指定范围
print(text.startswith("is", 7)) # True
# endswith():是否以指定字符串结尾
filename = "document.pdf"
print(filename.endswith(".pdf")) # True
print(filename.endswith(".txt")) # False
# isdigit():是否全是数字
print("123".isdigit()) # True
print("12.3".isdigit()) # False
print("12a".isdigit()) # False
# isalpha():是否全是字母
print("abc".isalpha()) # True
print("abc123".isalpha()) # False
# isalnum():是否全是字母或数字
print("abc123".isalnum()) # True
print("abc 123".isalnum()) # False
# isspace():是否全是空白字符
print(" ".isspace()) # True
print(" a ".isspace()) # False
# islower():是否全是小写
print("hello".islower()) # True
print("Hello".islower()) # False
# isupper():是否全是大写
print("HELLO".isupper()) # True
print("Hello".isupper()) # False
# istitle():是否是标题格式(每个单词首字母大写)
print("Hello World".istitle()) # True
print("Hello world".istitle()) # False
# ========== 对齐和填充 ==========
text = "Python"
# center():居中对齐
print(text.center(20)) # " Python "
print(text.center(20, "*")) # "*******Python*******"
# ljust():左对齐
print(text.ljust(20)) # "Python "
print(text.ljust(20, "-")) # "Python--------------"
# rjust():右对齐
print(text.rjust(20)) # " Python"
print(text.rjust(20, "-")) # "--------------Python"
# zfill():用0填充(常用于数字)
number = "42"
print(number.zfill(5)) # "00042"
# ========== 编码和解码 ==========
# encode():字符串转字节
text = "你好,世界"
bytes_data = text.encode("utf-8")
print(bytes_data) # b'\xe4\xbd\xa0\xe5\xa5\xbd\xef\xbc\x8c\xe4\xb8\x96\xe7\x95\x8c'
# decode():字节转字符串
decoded = bytes_data.decode("utf-8")
print(decoded) # 你好,世界
# ========== 格式化方法 ==========
# format():格式化字符串
name = "张三"
age = 25
text = "我叫{},今年{}岁".format(name, age)
print(text) # 我叫张三,今年25岁
# 指定位置
text = "我叫{0},今年{1}岁,{0}很高兴认识你".format(name, age)
print(text)
# 指定名称
text = "我叫{name},今年{age}岁".format(name=name, age=age)
print(text)
# format_map():用字典格式化
person = {"name": "李四", "age": 30}
text = "我叫{name},今年{age}岁".format_map(person)
print(text)
# ========== 其他实用方法 ==========
# partition():分割成三部分
text = "Python is awesome"
parts = text.partition("is")
print(parts) # ('Python ', 'is', ' awesome')
# rpartition():从右边分割
parts = text.rpartition("is")
print(parts) # ('Python ', 'is', ' awesome')
# expandtabs():展开制表符
text = "Name\tAge\tCity"
print(text.expandtabs(10)) # Name Age City
# translate():字符映射转换
# 创建转换表
trans_table = str.maketrans("aeiou", "12345")
text = "hello world"
print(text.translate(trans_table)) # h2ll4 w4rld
# 删除字符
trans_table = str.maketrans("", "", "aeiou")
print(text.translate(trans_table)) # hll wrld
十五、文件操作
1. 打开与关闭文件
在 Python 中,操作文件的基本流程是:打开文件 -> 操作文件 (读/写) -> 关闭文件。
1.1 open() 函数
open() 是 Python 的内置函数,用于打开一个文件并返回一个文件对象(File Object)。
基本语法:
file_object = open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None)
- file: 文件路径(相对路径或绝对路径)。
- mode: 文件打开模式(详见下一节)。
- encoding: 编码格式,处理文本文件时强烈建议指定(如
encoding='utf-8'),避免乱码。
1.2 close() 函数
文件操作完成后,必须调用 close() 方法释放系统资源。如果不关闭文件,可能会导致内存泄漏或数据未成功写入磁盘。
传统写法(不推荐):
f = open('example.txt', 'w', encoding='utf-8')
f.write('Hello, World!')
f.close() # 容易被遗忘,或在报错时无法执行到
1.3 使用 with 上下文管理器
为了防止忘记调用 close() 或者在读写过程中发生异常导致文件未关闭,Python 提供了 with 语句。它可以自动帮你管理文件的关闭,即使代码块中抛出了异常。
with open('example.txt', 'w', encoding='utf-8') as f:
f.write('Hello, Python!')
# 离开 with 代码块后,文件 f 已经被自动关闭
2. 文件打开模式 (Mode)
open() 函数的 mode 参数决定了你将以何种方式操作文件。以下是模式对照表:
| 模式 | 描述 | 特点说明 |
|---|---|---|
'r' |
只读 (默认) | 从头开始读。如果文件不存在,抛出 FileNotFoundError 异常。 |
'w' |
只写 | 覆盖已有文件。如果文件不存在,则创建新文件。 |
'x' |
独占创建 | 创建新文件并写入。如果文件已存在,则抛出 FileExistsError 异常。 |
'a' |
追加 | 在文件末尾追加内容。如果文件不存在,则创建新文件。 |
'b' |
二进制模式 | 与其他模式结合使用(如 'rb', 'wb'),用于处理非文本文件(图片、音频等)。 |
't' |
文本模式 (默认) | 与其他模式结合使用(如 'rt',通常省略 't')。 |
'+' |
读写模式 | 与其他模式结合使用(如 'r+', 'w+', 'a+'),使文件既可读也可写。 |
3. 读取文件 (Read)
Python 提供了多种读取文件内容的方法,适用于不同的场景。
3.1 read(size):读取指定字符或全部内容
- 说明:如果不指定
size,则一次性读取整个文件内容。 - 适用场景:文件较小,内存足够时。
with open('example.txt', 'r', encoding='utf-8') as f:
content = f.read()
print("全部内容:\n", content)
3.2 readline():逐行读取
- 说明:每次调用只读取文件中的一行(保留行尾的换行符
\n)。 - 适用场景:处理超大文件,内存有限时。
with open('example.txt', 'r', encoding='utf-8') as f:
line = f.readline()
while line:
print("单行内容:", line.strip()) # strip() 去除首尾空白符和换行符
line = f.readline()
3.3 readlines():读取所有行并返回列表
- 说明:将文件按行读取,每行作为列表中的一个元素。
with open('example.txt', 'r', encoding='utf-8') as f:
lines = f.readlines()
for line in lines:
print(line.strip())
3.4 遍历文件对象
文件对象本身就是一个可迭代对象(Iterable),这是处理大文件最推荐的方式。
with open('example.txt', 'r', encoding='utf-8') as f:
for line in f:
print(line.strip())
4. 写入文件 (Write)
写入文件同样有不同的方法,需要注意 'w' 模式会覆盖原文件,而 'a' 模式是在末尾追加。
4.1 write(string):写入字符串
- 说明:将字符串写入文件。注意,它不会自动帮你添加换行符,需要手动加
\n。
with open('output.txt', 'w', encoding='utf-8') as f:
f.write("这是第一行。\n")
f.write("这是第二行。\n")
4.2 writelines(iterable):写入可迭代对象
- 说明:接受一个字符串列表(或其它可迭代对象)并写入文件。同样,它不会自动添加换行符。
lines_to_write = ["苹果\n", "香蕉\n", "橙子\n"]
with open('fruits.txt', 'w', encoding='utf-8') as f:
f.writelines(lines_to_write)
5. 文件指针
文件操作有一个“指针”(光标)的概念,记录着当前读写到的位置。
5.1 tell():获取当前指针位置
- 返回:当前文件指针相对于文件开头的字节数。
5.2 seek(offset, whence):移动文件指针
- offset:偏移的字节数。
- whence:相对位置。
0表示从文件开头算起(默认);1表示从当前位置算起;2表示从文件末尾算起。(注意:在文本模式下,whence只能为0;如果要使用1或2,通常需要以二进制模式'rb'打开)。
with open('example.txt', 'rb') as f: # 二进制模式
print(f.read(5)) # 读取前5个字节
print(f.tell()) # 输出当前指针位置: 5
f.seek(0, 0) # 将指针移回文件开头
print(f.read(3)) # 重新从头读取3个字节
f.seek(-2, 2) # 将指针移动到倒数第2个字节处
print(f.read()) # 读取最后两个字节
好的!虽然我无法直接访问该 CSDN 链接,但根据我对该类高质量文章的了解,我为您的博客大幅扩充了以下内容。这些章节可以直接无缝衔接到您现有的第 5 节之后,让整篇博客从"基础读写"跃升为"全方位文件操作手册"。
6. 文件对象的其他常用属性与方法
除了前面介绍的读写和指针操作外,文件对象本身还有一些非常实用的属性和方法。
6.1 文件对象的常用属性
| 属性 | 说明 |
|---|---|
f.name |
返回文件的名称(路径) |
f.mode |
返回文件打开时使用的模式 |
f.closed |
判断文件是否已经关闭,返回 True 或 False |
f.encoding |
返回文件使用的编码格式(仅文本模式) |
with open('example.txt', 'r', encoding='utf-8') as f:
print("文件名:", f.name) # example.txt
print("打开模式:", f.mode) # r
print("编码格式:", f.encoding) # utf-8
print("是否已关闭:", f.closed) # False
print("离开 with 后是否已关闭:", f.closed) # True
6.2 flush():强制刷新缓冲区
- 说明:
write()在调用时,数据不一定会立即写入磁盘,可能会暂时存在内存的缓冲区中。调用flush()可以强制将缓冲区的数据立即写入文件,而无需等待文件关闭。 - 适用场景:在实时日志记录、长时间运行脚本中非常有用,可以防止程序意外中断时丢失数据。
import time
with open('realtime_log.txt', 'w', encoding='utf-8') as f:
for i in range(5):
f.write(f"日志记录 {i}: 当前时间 {time.strftime('%H:%M:%S')}\n")
f.flush() # 每写一条就立即刷新到磁盘,防止崩溃时丢失
print(f"第 {i} 条日志已写入磁盘")
time.sleep(1) # 模拟耗时操作
6.3 truncate(size):截断文件
- 说明:将文件截断到指定的
size字节。如果不指定size,则从当前文件指针位置截断(即删除指针之后的所有内容)。 - 注意:需要以可写模式(如
'r+','w','a')打开文件。
# 先准备一个文件
with open('trunc_test.txt', 'w', encoding='utf-8') as f:
f.write("Hello, Python World!") # 20个字符
# 截断文件,只保留前 13 个字节
with open('trunc_test.txt', 'r+', encoding='utf-8') as f:
f.truncate(13)
with open('trunc_test.txt', 'r', encoding='utf-8') as f:
print(f.read()) # 输出: Hello, Python
7. 文件编码与乱码问题
编码问题是文件操作中最常见的坑之一,尤其是在跨平台(Windows / Mac / Linux)开发时。
7.1 什么是文件编码?
文件在磁盘上本质是一串二进制字节流。编码(Encoding)就是"字符"与"字节"之间的映射规则。常见编码:
| 编码 | 说明 |
|---|---|
ASCII |
最早的编码,仅支持 128 个英文字符,1 字节/字符 |
GBK / GB2312 |
中文编码标准,Windows 中文系统默认编码,2 字节/中文 |
UTF-8 |
国际通用编码,可变长度(英文 1 字节,中文 3 字节),推荐使用 |
7.2 乱码产生的原因
核心原因:写入时用的编码 ≠ 读取时用的编码
# 用 GBK 编码写入
with open('gbk_file.txt', 'w', encoding='gbk') as f:
f.write('你好,世界')
# 用 UTF-8 编码读取 —— 产生乱码或报错!
try:
with open('gbk_file.txt', 'r', encoding='utf-8') as f:
print(f.read())
except UnicodeDecodeError as e:
print(f"解码错误: {e}")
7.3 解决方案:检测文件编码
当你拿到一个不确定编码的文件时,可以使用第三方库 chardet 来自动检测。
pip install chardet
import chardet
# 以二进制模式读取原始字节
with open('gbk_file.txt', 'rb') as f:
raw_data = f.read()
result = chardet.detect(raw_data)
print("检测结果:", result)
# 输出类似: {'encoding': 'GB2312', 'confidence': 0.99, 'language': 'Chinese'}
# 用检测到的编码去正确读取
detected_encoding = result['encoding']
with open('gbk_file.txt', 'r', encoding=detected_encoding) as f:
print("正确内容:", f.read()) # 你好,世界
7.4 编码转换实战:GBK 转 UTF-8
def convert_encoding(src_file, dst_file, src_enc='gbk', dst_enc='utf-8'):
"""将文件从一种编码转换为另一种编码"""
with open(src_file, 'r', encoding=src_enc) as f_in:
content = f_in.read()
with open(dst_file, 'w', encoding=dst_enc) as f_out:
f_out.write(content)
print(f"已将 {src_file} 从 {src_enc} 转换为 {dst_enc},保存到 {dst_file}")
convert_encoding('gbk_file.txt', 'utf8_file.txt')
8. 二进制文件操作
图片、音频、视频、可执行文件等都属于二进制文件,不能以文本模式打开,必须使用 'b' 模式。
8.1 复制二进制文件(如图片)
def copy_binary_file(src, dst, chunk_size=1024):
"""
以二进制方式复制文件(适用于任何文件类型)
chunk_size: 每次读取的字节数,避免大文件撑爆内存
"""
with open(src, 'rb') as f_in, open(dst, 'wb') as f_out:
while True:
chunk = f_in.read(chunk_size)
if not chunk: # 读完了
break
f_out.write(chunk)
print(f"文件复制完成: {src} -> {dst}")
# 示例:复制一张图片
# copy_binary_file('photo.jpg', 'photo_backup.jpg')
知识点:上面的
with open(...) as f_in, open(...) as f_out:语法可以同时打开两个文件,它们都会在退出with块时自动关闭。
8.2 读取文件的二进制头部(判断文件类型)
不同类型的文件有不同的"魔数"(Magic Number),即文件开头的几个字节。通过读取这些字节,我们可以判断文件的真实类型,而不是依赖文件后缀名。
def detect_file_type(filepath):
"""通过文件头部的魔数判断文件类型"""
magic_numbers = {
b'\x89PNG': 'PNG 图片',
b'\xff\xd8\xff': 'JPEG 图片',
b'GIF8': 'GIF 图片',
b'PK': 'ZIP 压缩文件 (或 .docx/.xlsx)',
b'%PDF': 'PDF 文档',
}
with open(filepath, 'rb') as f:
header = f.read(8) # 读取前8个字节即可
for magic, file_type in magic_numbers.items():
if header.startswith(magic):
return file_type
return '未知类型'
# print(detect_file_type('test.png')) # PNG 图片
十六、数据可视化
Python的数据可视化生态非常强大,最常用的库是matplotlib和seaborn。通过几行代码就能把枯燥的数据变成直观的图表。
安装必要的库
# 在终端中执行
# pip install matplotlib seaborn pandas numpy
matplotlib基础
matplotlib是Python最基础的绑图库,几乎所有其他可视化库都是基于它构建的。
import matplotlib.pyplot as plt
# 最简单的折线图
x = [1, 2, 3, 4, 5]
y = [2, 4, 6, 8, 10]
plt.plot(x, y)
plt.title("My First Plot")
plt.xlabel("X Axis")
plt.ylabel("Y Axis")
plt.show()
中文显示设置
matplotlib默认不支持中文,需要手动设置字体:
import matplotlib.pyplot as plt
# Windows系统
plt.rcParams['font.sans-serif'] = ['SimHei']
# macOS系统
# plt.rcParams['font.sans-serif'] = ['Arial Unicode MS']
# Linux系统
# plt.rcParams['font.sans-serif'] = ['WenQuanYi Micro Hei']
# 解决负号显示问题
plt.rcParams['axes.unicode_minus'] = False
# 现在可以正常显示中文了
plt.plot([1, 2, 3], [4, 5, 6])
plt.title("我的第一张图")
plt.xlabel("横轴")
plt.ylabel("纵轴")
plt.show()
折线图
import matplotlib.pyplot as plt
# 模拟一周的气温数据
days = ["周一", "周二", "周三", "周四", "周五", "周六", "周日"]
temperature = [23, 25, 22, 26, 28, 30, 27]
plt.figure(figsize=(10, 6),dpi=80) # 设置图表大小
# 在图片模糊的时候调整dpi来变清晰
plt.plot(days, temperature, marker='o', color='tomato', linewidth=2)
plt.title("本周气温变化", fontsize=16)
plt.xlabel("日期", fontsize=12)
plt.ylabel("温度 (°C)", fontsize=12)
plt.grid(True, linestyle='--', alpha=0.7) # 添加网格线
plt.show()
多条折线对比
import matplotlib.pyplot as plt
months = ["1月", "2月", "3月", "4月", "5月", "6月"]
beijing = [2, 5, 12, 20, 26, 30]
shanghai = [5, 7, 12, 18, 23, 28]
guangzhou = [14, 15, 18, 23, 27, 30]
plt.figure(figsize=(10, 6))
plt.plot(months, beijing, marker='o', label="北京")
plt.plot(months, shanghai, marker='s', label="上海")
plt.plot(months, guangzhou, marker='^', label="广州")
plt.title("三城市上半年气温对比", fontsize=16)
plt.xlabel("月份", fontsize=12)
plt.ylabel("温度 (°C)", fontsize=12)
plt.legend(fontsize=12) # 显示图例
plt.grid(True, linestyle='--', alpha=0.5)
plt.show()
柱状图
import matplotlib.pyplot as plt
# 编程语言受欢迎程度
languages = ["Python", "JavaScript", "Java", "C++", "Go"]
popularity = [35, 25, 20, 12, 8]
colors = ['#3776AB', '#F7DF1E', '#ED8B00', '#00599C', '#00ADD8']
plt.figure(figsize=(10, 6))
bars = plt.bar(languages, popularity, color=colors, edgecolor='white', width=0.6)
# 在柱子上方显示数值
for bar in bars:
height = bar.get_height()
plt.text(bar.get_x() + bar.get_width() / 2., height + 0.5,
f'{height}%', ha='center', fontsize=12)
plt.title("2024年编程语言受欢迎程度", fontsize=16)
plt.xlabel("编程语言", fontsize=12)
plt.ylabel("占比 (%)", fontsize=12)
plt.ylim(0, 40) # 设置y轴范围
plt.show()
分组柱状图
import matplotlib.pyplot as plt
import numpy as np
# 两个学期的成绩对比
subjects = ["语文", "数学", "英语", "物理", "化学"]
semester1 = [85, 78, 92, 70, 75]
semester2 = [88, 85, 90, 80, 82]
x = np.arange(len(subjects)) # 标签位置
width = 0.35 # 柱子宽度
plt.figure(figsize=(10, 6))
bars1 = plt.bar(x - width/2, semester1, width, label='上学期', color='steelblue')
bars2 = plt.bar(x + width/2, semester2, width, label='下学期', color='coral')
plt.title("两学期成绩对比", fontsize=16)
plt.xlabel("科目", fontsize=12)
plt.ylabel("分数", fontsize=12)
plt.xticks(x, subjects)
plt.legend(fontsize=12)
plt.ylim(60, 100)
plt.show()
饼图
import matplotlib.pyplot as plt
# 时间分配
activities = ["学习", "睡觉", "娱乐", "运动", "吃饭", "其他"]
hours = [8, 7, 3, 2, 2, 2]
colors = ['#ff9999', '#66b3ff', '#99ff99', '#ffcc99', '#ff66b3', '#c2c2f0']
explode = (0.05, 0, 0, 0, 0, 0) # 突出显示"学习"
plt.figure(figsize=(8, 8))
plt.pie(hours, labels=activities, colors=colors, explode=explode,
autopct='%1.1f%%', startangle=90, textprops={'fontsize': 12})
plt.title("一天时间分配", fontsize=16)
plt.axis('equal') # 保证是正圆
plt.show()
散点图
import matplotlib.pyplot as plt
import numpy as np
# 模拟身高体重数据
np.random.seed(42)
height = np.random.normal(170, 8, 100) # 100个人的身高
weight = height * 0.6 + np.random.normal(0, 5, 100) # 体重和身高有相关性
plt.figure(figsize=(10, 6))
plt.scatter(height, weight, alpha=0.6, c='steelblue', edgecolors='white', s=60)
plt.title("身高与体重的关系", fontsize=16)
plt.xlabel("身高 (cm)", fontsize=12)
plt.ylabel("体重 (kg)", fontsize=12)
plt.grid(True, linestyle='--', alpha=0.5)
plt.show()
直方图
import matplotlib.pyplot as plt
import numpy as np
# 模拟考试成绩分布
np.random.seed(42)
scores = np.random.normal(75, 10, 200) # 200个学生,均值75,标准差10
plt.figure(figsize=(10, 6))
plt.hist(scores, bins=20, color='steelblue', edgecolor='white', alpha=0.7)
plt.title("考试成绩分布", fontsize=16)
plt.xlabel("分数", fontsize=12)
plt.ylabel("人数", fontsize=12)
plt.axvline(x=np.mean(scores), color='red', linestyle='--', label=f'平均分: {np.mean(scores):.1f}')
plt.legend(fontsize=12)
plt.show()
子图(多图组合)
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(0, 2 * np.pi, 100)
fig, axes = plt.subplots(2, 2, figsize=(12, 8))
# 左上:正弦
axes[0, 0].plot(x, np.sin(x), color='steelblue')
axes[0, 0].set_title("sin(x)")
axes[0, 0].grid(True, alpha=0.3)
# 右上:余弦
axes[0, 1].plot(x, np.cos(x), color='coral')
axes[0, 1].set_title("cos(x)")
axes[0, 1].grid(True, alpha=0.3)
# 左下:正切(限制范围)
axes[1, 0].plot(x, np.sin(x) ** 2, color='green')
axes[1, 0].set_title("sin²(x)")
axes[1, 0].grid(True, alpha=0.3)
# 右下:组合
axes[1, 1].plot(x, np.sin(x), label='sin(x)')
axes[1, 1].plot(x, np.cos(x), label='cos(x)')
axes[1, 1].set_title("sin(x) & cos(x)")
axes[1, 1].legend()
axes[1, 1].grid(True, alpha=0.3)
plt.tight_layout() # 自动调整间距
plt.show()
seaborn进阶可视化
seaborn是基于matplotlib的高级封装,用更少的代码画出更好看的图。
import seaborn as sns
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
# 设置seaborn风格
sns.set_theme(style="whitegrid")
# 创建示例数据
np.random.seed(42)
data = pd.DataFrame({
"月份": list(range(1, 13)) * 3,
"销售额": np.random.randint(100, 500, 36),
"城市": ["北京"] * 12 + ["上海"] * 12 + ["广州"] * 12
})
plt.figure(figsize=(10, 6))
sns.lineplot(data=data, x="月份", y="销售额", hue="城市", marker='o')
plt.title("各城市月度销售额", fontsize=16)
plt.show()
热力图
import seaborn as sns
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
# 模拟各科目之间的相关性
subjects = ["语文", "数学", "英语", "物理", "化学", "生物"]
np.random.seed(42)
data = np.random.rand(6, 6)
# 让矩阵对称,模拟相关系数
data = (data + data.T) / 2
np.fill_diagonal(data, 1)
df = pd.DataFrame(data, index=subjects, columns=subjects)
plt.figure(figsize=(8, 6))
sns.heatmap(df, annot=True, fmt='.2f', cmap='coolwarm',
vmin=0, vmax=1, linewidths=0.5)
plt.title("各科目成绩相关性", fontsize=16)
plt.show()
箱线图
import seaborn as sns
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
# 模拟不同班级的成绩
np.random.seed(42)
data = pd.DataFrame({
"成绩": np.concatenate([
np.random.normal(75, 10, 50),
np.random.normal(80, 8, 50),
np.random.normal(70, 12, 50)
]),
"班级": ["一班"] * 50 + ["二班"] * 50 + ["三班"] * 50
})
plt.figure(figsize=(8, 6))
sns.boxplot(data=data, x="班级", y="成绩", palette="Set2")
plt.title("各班级成绩分布", fontsize=16)
plt.show()
保存图表
import matplotlib.pyplot as plt
plt.plot([1, 2, 3], [4, 5, 6])
plt.title("示例图表")
# 保存为不同格式
plt.savefig("chart.png", dpi=300, bbox_inches='tight') # PNG格式,高清
plt.savefig("chart.pdf", bbox_inches='tight') # PDF格式,矢量图
plt.savefig("chart.svg", bbox_inches='tight') # SVG格式,网页用
# bbox_inches='tight' 会去掉多余的空白边距
# dpi=300 设置分辨率,适合打印
plt.show()
实战:用一份数据画完整报告
import matplotlib.pyplot as plt
import numpy as np
# 模拟电商数据
np.random.seed(42)
months = [f"{i}月" for i in range(1, 13)]
revenue = np.random.randint(50, 150, 12) # 月收入(万元)
orders = np.random.randint(500, 2000, 12) # 订单数
categories = ["电子产品", "服装", "食品", "家居", "图书"]
category_sales = [35, 25, 20, 12, 8]
fig, axes = plt.subplots(2, 2, figsize=(14, 10))
fig.suptitle("2024年电商数据分析报告", fontsize=18, fontweight='bold')
# 左上:月收入趋势
axes[0, 0].plot(months, revenue, marker='o', color='steelblue', linewidth=2)
axes[0, 0].fill_between(range(12), revenue, alpha=0.1, color='steelblue')
axes[0, 0].set_title("月收入趋势", fontsize=14)
axes[0, 0].set_ylabel("收入(万元)")
axes[0, 0].tick_params(axis='x', rotation=45)
axes[0, 0].grid(True, alpha=0.3)
# 右上:月订单量
axes[0, 1].bar(months, orders, color='coral', edgecolor='white')
axes[0, 1].set_title("月订单量", fontsize=14)
axes[0, 1].set_ylabel("订单数")
axes[0, 1].tick_params(axis='x', rotation=45)
# 左下:品类占比
axes[1, 0].pie(category_sales, labels=categories, autopct='%1.1f%%',
colors=['#ff9999', '#66b3ff', '#99ff99', '#ffcc99', '#c2c2f0'])
axes[1, 0].set_title("品类销售占比", fontsize=14)
# 右下:收入与订单的关系
axes[1, 1].scatter(orders, revenue, c='steelblue', alpha=0.7, s=80, edgecolors='white')
axes[1, 1].set_title("订单量与收入关系", fontsize=14)
axes[1, 1].set_xlabel("订单数")
axes[1, 1].set_ylabel("收入(万元)")
axes[1, 1].grid(True, alpha=0.3)
plt.tight_layout()
plt.savefig("ecommerce_report.png", dpi=300, bbox_inches='tight')
plt.show()
更多推荐

所有评论(0)