Skip to content

字符串格式化、文件操作、异常处理

字符串格式化

f-string

3.6 之后版本支持的格式化字符串,在字符串的引号前加上 f,通过 {} 来引用变量或者表达式。

python
name = 'Alice'
age = 25
print(f'My name is {name} and I am {age} years old.')

除了常规的输出,还可以用来格式化时间,数字等。

python
import datetime

now = datetime.datetime.now()
print(f'The current time is {now: %Y-%m-%d %H:%M:%S}.')

冒号后可以指定格式化字符串,比如 %Y-%m-%d %H:%M:%S 表示年月日时分秒。也可以针对数字做出操作,比如 {num:.2f} 表示保留两位小数,会自动四舍五入。

假设你有一个很大的数字 100000 想格式化为 100,000,可以使用 {num:,} 来实现。再保留两位小数,可以使用 {num:,.2f} 来实现。

输出的对齐,可以使用 {num:>10} 来实现,表示右对齐,{num:<10} 表示左对齐,{num:^10} 表示居中对齐。默认情况下是左对齐。并且会用空格填充。也可以指定填充的内容。

python
num = 123
print(f'{num:>10}') 
print(f'{num:<10}') 
print(f'{num:^10}')
print(f'{num:*^10}')

format 方法

基本与 f-string 类似,但是需要使用 {} 来引用变量或者表达式。

python
print('Hello {}!'.format(name))
print('{:%Y-%m-%d %H-%M-%S}'.format(datetime.datetime.now()))
print('{:.2f}'.format(1000))
print('{:,.2f}'.format(1000))
print('{:>10}'.format(1000))
print('{:<10}'.format(1000))
print('{:^10}'.format(1000))

多个参数时,可以使用 {index} 来指定参数的索引。也可以使用 {key} 来指定参数的键。

python
print('{0}, {1}'.format(name, age))
print('{1}, {0}'.format(age, name))
print('{name} {age}'.format(name='Alice', age=25))
print('{name} {age}'.format(age=25, name='Alice'))

旧式格式化

3.6 之前版本支持的格式化字符串,使用 % 来引用变量或者表达式。

python
print('%s %d' % (name, age))
print('%d %s' % (age, name))

% 为占位符,%s 表示字符串,%d 表示整数,%f 表示浮点数。

文件操作

open 函数用于打开文件,返回一个文件对象。有三种模式:

  • r 读取模式,默认模式。
  • w 写入模式,会覆盖原有文件。
  • a 追加模式,在原有文件基础上追加内容。
  • b 二进制模式,用于读取二进制文件。
  • r+ 读写模式,可以读取和写入文件。
  • w+ 写读模式,可以写入和读取文件。
  • a+ 追加读模式,可以追加和读取文件。
  • b+ 二进制读写模式,可以读取和写入二进制文件。

encoding 参数用于指定文件的编码格式,如果不指定,则使用系统默认编码。

python
file = open('test.txt', 'r', encoding='utf-8')

print(file.closed) # False

file.close()
print(file.closed) # True

open 的方式需要手动的关闭文件,可以使用 with 语句来自动关闭文件。

python
with open('test.txt', 'r', encoding='utf-8') as file:
    print(file.read())

print(file.closed) # True

文件的读写方法

方法描述
read(size=-1)读取文件内容,size 为读取的字节数,默认读取全部
readline(size=-1)读取文件的一行内容,size 为读取的字节数,默认读取整行
readlines(hint=-1)读取文件的所有行内容,hint 为读取的行数,默认读取所有行
write(str)写入字符串内容到文件
writelines(lines)写入字符串列表到文件,每个元素为一行
seek(offset, whence=0)移动文件指针,offset 为偏移量,whence 为起始位置(0开头,1当前,2结尾)
tell()获取文件指针当前位置
close()关闭文件
readable()判断文件是否可读
writable()判断文件是否可写
closed判断文件是否已关闭
python
with open('test.txt', 'r', encoding='utf-8') as file:
    print(file.readable())
    print(file.writable())
    print(file.closed)

readline 如果返回空字符串,标识文件句柄已经到达文件末尾。

seek 方法用于移动文件指针,可以指定偏移量和起始位置。默认从 0 开始。

python
# 在距离文件开头 50 字节处开始写入内容
with open('test.txt', 'r+', encoding='utf-8') as file:
    file.seek(50)
    file.write('Hello, world!')

json 序列化

json 是 JavaScript Object Notation 的缩写,是一种轻量级的数据交换格式。

json 序列化:将 Python 对象转换为 json 字符串。

json 反序列化:将 json 字符串转换为 Python 对象。

python
import json

# 序列化
json_str = json.dumps(data)

# 反序列化
data = json.loads(json_str)

错误和异常

语法错误又称为解析错误,指代码不符合 Python 语法规则。

python
while True print('Hello world')
  File "<stdin>", line 1
    while True print('Hello world')
               ^^^^^
SyntaxError: invalid syntax

异常指程序运行时发生的错误,比如除以 0,文件不存在等。 在报错信息中,最后一行是异常类型,前面是异常发生的文件和行号。

python
Traceback (most recent call last):
  File "/Users/xushuqing/Documents/learn-codes/learn-python/code_1.py", line 45, in <module>
    print(10 / 0)
ZeroDivisionError: division by zero

异常也分为内置异常和自定义异常。常见的异常多种多样,实际问题实际解决。https://docs.python.org/zh-cn/3/library/exceptions.html#bltin-exceptions

异常的处理

python
while True:
    try:
        x = int(input("Please enter a number: "))
        break
    except ValueError:
        print("Oops!  That was no valid number.  Try again...")

try 语句用于捕获异常,except 语句用于处理异常,finally 语句用于执行清理操作。finally 语句是可选的,用于执行一些清理操作,比如关闭文件,释放资源等。

如果被 try 包裹的代码块没有发生异常,则 except 语句不会被执行。finally 语句会始终被执行。

一个 except 语句可以捕获多个异常,使用元组来表示。但不会同时捕获多个异常。

python
try:
    print(10 / 0)
except (ZeroDivisionError, ValueError):
    print("Oops!  That was no valid number.  Try again...")

在自定义的异常中,可以继承内置异常,并添加自己的异常信息。多个 except 语句可以捕获不同的异常。如果多个异常类则匹配到基类, 如果基类匹配到则不会继续往下执行 如下

python
class A(Exception):
    pass

class B(A):
    pass

class C(B):
    pass

# 打印 A A A 
for i in [A, B]:
    try:
        raise i()
    except A:
        print("A")
    except B:
        print("B")
    except C:
        print("C")

# 打印 A B C
for i in [A, B]:
    try:
        raise i()
    except C:
        print("C")
    except B:
        print("B")
    except A:
        print("A")

触发异常

raise 语句用于触发异常。参数必须是异常类或者异常实例。

python
raise ValueError('错误信息')
异常描述
Exception所有异常的基类
ValueError值错误
TypeError类型错误
NameError名称错误
IndexError索引错误
KeyError键错误
FileNotFoundError文件未找到错误
ZeroDivisionError除以 0 错误
StopIteration迭代器没有更多的值
KeyboardInterrupt用户中断执行
SystemExit解释器请求退出
MemoryError内存溢出错误
ImportError导入模块/对象失败
AttributeError对象没有这个属性

无脑的 异常处理 - 捕获所有异常

python
try:
    raise Exception('错误信息')
except Exception as e:
    # 实际开发的时候可以使用这个先兜底
    print(e)

练习题

基础练习

  1. 字符串格式化

    python
    # 有以下变量:
    name = "Alice"
    age = 25
    height = 1.68
    # 使用三种不同的字符串格式化方式完成以下输出:
    # "My name is Alice, I'm 25 years old and 1.68m tall."
    # 要求:height 保留两位小数
  2. 文件读写

    python
    # 创建一个程序,要求:
    # 1. 创建一个文件 'names.txt',写入三个名字,每个名字占一行
    # 2. 读取文件内容,将每个名字转换为大写
    # 3. 将转换后的内容写入新文件 'upper_names.txt'
  3. JSON 处理

    python
    # 有以下 Python 字典:
    student = {
        'name': 'Bob',
        'age': 20,
        'scores': {
            'math': 95,
            'english': 89,
            'history': 92
        }
    }
    # 要求:
    # 1. 将字典转换为 JSON 字符串
    # 2. 将 JSON 字符串保存到文件
    # 3. 从文件读取 JSON 字符串并转换回 Python 对象

进阶练习

  1. 文件处理与异常处理

    python
    # 编写一个函数 safe_read_file(filename),要求:
    # 1. 读取指定的文本文件内容
    # 2. 处理可能发生的异常(文件不存在、权限不足等)
    # 3. 如果文件不存在,返回"File not found"
    # 4. 如果读取成功,返回文件内容
  2. 高级字符串格式化

    python
    # 创建一个函数 format_student_info(students),接收一个学生列表:
    students = [
        {'name': 'Alice', 'age': 25, 'score': 95},
        {'name': 'Bob', 'age': 23, 'score': 88},
        {'name': 'Charlie', 'age': 24, 'score': 92}
    ]
    # 要求:
    # 1. 输出一个格式化的表格,包含姓名、年龄和分数
    # 2. 分数需要显示为百分比形式(95.00%)
    # 3. 表格要求左对齐

挑战题

  1. 成绩单处理程序
    python
    # 实现一个成绩单处理程序,要求:
    # 1. 从文件 'scores.txt' 中读取学生成绩数据
    #    文件格式:每行一条记录,格式为 "姓名,分数"
    #    例如:
    #    Alice,95
    #    Bob,88
    #    Charlie,92
    # 2. 处理数据并计算:
    #    - 班级平均分
    #    - 最高分和最低分
    #    - 分数段统计(90-100, 80-89, 70-79, 60-69, <60)
    # 3. 将统计结果保存为 JSON 格式的文件
    # 4. 处理所有可能的异常(文件不存在、格式错误等)

参考答案

点击查看答案

基础练习答案

  1. 字符串格式化

    python
    name = "Alice"
    age = 25
    height = 1.68
    
    # f-string
    print(f"My name is {name}, I'm {age} years old and {height:.2f}m tall.")
    
    # format 方法
    print("My name is {}, I'm {} years old and {:.2f}m tall.".format(name, age, height))
    
    # % 操作符
    print("My name is %s, I'm %d years old and %.2fm tall." % (name, age, height))
  2. 文件读写

    python
    # 写入原始文件
    with open('names.txt', 'w', encoding='utf-8') as f:
        f.write('alice\nbob\ncharlie\n')
    
    # 读取并转换
    with open('names.txt', 'r', encoding='utf-8') as f:
        names = [name.strip().upper() for name in f.readlines()]
    
    # 写入新文件
    with open('upper_names.txt', 'w', encoding='utf-8') as f:
        f.write('\n'.join(names) + '\n')
  3. JSON 处理

    python
    import json
    
    student = {
        'name': 'Bob',
        'age': 20,
        'scores': {
            'math': 95,
            'english': 89,
            'history': 92
        }
    }
    
    # 转换为 JSON 字符串
    json_str = json.dumps(student, indent=4)
    
    # 保存到文件
    with open('student.json', 'w') as f:
        f.write(json_str)
    
    # 读取并转换回 Python 对象
    with open('student.json', 'r') as f:
        loaded_student = json.loads(f.read())
    
    print(loaded_student == student)  # True

进阶练习答案

  1. 文件处理与异常处理

    python
    def safe_read_file(filename):
        try:
            with open(filename, 'r', encoding='utf-8') as f:
                return f.read()
        except FileNotFoundError:
            return "File not found"
        except PermissionError:
            return "Permission denied"
        except Exception as e:
            return f"Error: {str(e)}"
  2. 高级字符串格式化

    python
    def format_student_info(students):
        # 创建表头
        header = f"{'Name':<10}{'Age':<6}{'Score':<8}"
        separator = "-" * 24
        
        # 创建数据行
        rows = []
        for student in students:
            row = f"{student['name']:<10}{student['age']:<6}{student['score']:.2f}%"
            rows.append(row)
        
        # 组合所有行
        return "\n".join([header, separator] + rows)

挑战题答案

  1. 成绩单处理程序
    python
    import json
    from collections import defaultdict
    
    def process_scores(filename):
        try:
            # 读取文件
            scores = []
            with open(filename, 'r', encoding='utf-8') as f:
                for line in f:
                    name, score = line.strip().split(',')
                    scores.append((name, float(score)))
            
            # 计算统计数据
            score_values = [score for _, score in scores]
            stats = {
                'average': sum(score_values) / len(score_values),
                'highest': max(score_values),
                'lowest': min(score_values),
                'distribution': {
                    '90-100': len([s for s in score_values if 90 <= s <= 100]),
                    '80-89': len([s for s in score_values if 80 <= s < 90]),
                    '70-79': len([s for s in score_values if 70 <= s < 80]),
                    '60-69': len([s for s in score_values if 60 <= s < 70]),
                    '<60': len([s for s in score_values if s < 60])
                }
            }
            
            # 保存结果
            with open('score_stats.json', 'w', encoding='utf-8') as f:
                json.dump(stats, f, indent=4)
                
            return stats
            
        except FileNotFoundError:
            return "Error: File not found"
        except ValueError:
            return "Error: Invalid file format"
        except Exception as e:
            return f"Error: {str(e)}"
    
    # 测试代码
    if __name__ == "__main__":
        result = process_scores('scores.txt')
        print(result)

TIP

建议先独立完成练习,遇到困难时再参考答案。这样能够更好地掌握所学知识。