《前后端面试题
》专栏集合了前后端各个知识模块的面试题,包括html,javascript,css,vue,react,java,Openlayers,leaflet,cesium,mapboxGL,threejs,nodejs,mangoDB,SQL,Linux… 。
文章目录
- 一、本文面试题目录
- 71. Python中打开文件的模式有哪些?(如`r`、`w`、`a`、`rb`、`wb`等)
- 72. 如何读取文件内容?(`read()`、`readline()`、`readlines()`的区别)
- 73. 什么是上下文管理器(`with`语句)?它的优势是什么?
- 74. 如何写入文件内容?
- 75. 如何处理CSV文件?(使用`csv`模块或`pandas`)
- 1. 使用`csv`模块(标准库)
- 2. 使用`pandas`库(第三方库)
- 76. 如何遍历一个目录下的所有文件和子目录?(`os.walk()`)
- 77. 如何获取文件的大小、创建时间、修改时间?
- 方法1:使用 `os` 模块
- 方法2:使用 `pathlib` 模块(面向对象风格)
- 78. 如何重命名或删除文件/目录?
- 1. 重命名文件/目录
- 2. 删除文件/目录
- 79. 什么是二进制文件和文本文件?它们的操作有何区别?
- 定义
- 操作区别
- 示例
- 关键区别总结
- 80. 如何处理大文件(内存无法一次性加载)?
- 核心原则
- 常用方法
- 注意事项
- 二、150道Python面试题目录列表
一、本文面试题目录
71. Python中打开文件的模式有哪些?(如r
、w
、a
、rb
、wb
等)
在Python中,使用open()
函数打开文件时,需要指定文件模式,用于定义文件的操作方式(读/写)和数据类型(文本/二进制)。常见的文件模式如下:
模式 | 含义 | 说明 |
---|---|---|
r | 只读(默认) | 打开已存在的文件,若文件不存在则报错;指针位于文件开头。 |
w | 只写 | 打开文件用于写入,若文件不存在则创建,若已存在则清空内容;指针位于文件开头。 |
a | 追加 | 打开文件用于写入,若文件不存在则创建,新内容追加到文件末尾;指针位于文件末尾。 |
r+ | 读写 | 打开文件用于读写,文件必须存在;指针位于文件开头。 |
w+ | 读写 | 打开文件用于读写,若文件不存在则创建,若已存在则清空内容。 |
a+ | 读写 | 打开文件用于读写,若文件不存在则创建,写入时追加到末尾,读时需移动指针。 |
rb | 二进制只读 | 以二进制模式打开文件只读(用于非文本文件,如图片、音频)。 |
wb | 二进制只写 | 以二进制模式打开文件只写。 |
ab | 二进制追加 | 以二进制模式打开文件追加。 |
rb+ /wb+ /ab+ | 二进制读写 | 结合二进制和读写功能的模式。 |
示例:
# 只读模式打开文本文件
with open("test.txt", "r", encoding="utf-8") as f:content = f.read()# 只写模式打开文本文件(覆盖原有内容)
with open("output.txt", "w", encoding="utf-8") as f:f.write("Hello, World!")# 追加模式打开文本文件
with open("log.txt", "a", encoding="utf-8") as f:f.write("New log entry\n")# 二进制模式读取图片
with open("image.png", "rb") as f:data = f.read()
注意:
- 文本模式(无
b
)需指定encoding
(如utf-8
),用于字符编码转换;二进制模式(有b
)直接操作字节,无需编码。 - 写入时若不指定
encoding
,默认使用系统编码,可能导致跨平台兼容性问题。
72. 如何读取文件内容?(read()
、readline()
、readlines()
的区别)
Python文件对象提供了多种读取内容的方法,核心区别在于读取范围和返回值格式:
方法 | 功能 | 返回值 | 适用场景 |
---|---|---|---|
read(size) | 读取指定字节数(文本模式下为字符数),若未指定则读取全部内容。 | 字符串(文本模式)或字节串(二进制模式)。 | 读取小文件或需要一次性获取全部内容时。 |
readline(size) | 读取一行内容,包括换行符\n ;size 限制最大读取长度。 | 单行字符串(或字节串),若到文件末尾返回空字符串。 | 逐行读取大文件,节省内存。 |
readlines(hint) | 读取所有行,hint 为可选参数,限制总字符数(约)。 | 包含所有行的列表,每行作为列表元素。 | 需要按行处理且文件不大时。 |
示例:
假设有test.txt
文件内容如下:
第一行内容
第二行内容
第三行内容
-
read()
示例:with open("test.txt", "r", encoding="utf-8") as f:# 读取全部内容content = f.read()print(content)# 输出:# 第一行内容# 第二行内容# 第三行内容# 读取前5个字符f.seek(0) # 指针移回开头part = f.read(5)print(part) # 第一行内
-
readline()
示例:with open("test.txt", "r", encoding="utf-8") as f:line1 = f.readline()line2 = f.readline()print(line1) # 第一行内容(包含换行符)print(line2) # 第二行内容
-
readlines()
示例:with open("test.txt", "r", encoding="utf-8") as f:lines = f.readlines()print(type(lines)) # <class 'list'>print(lines) # ['第一行内容\n', '第二行内容\n', '第三行内容']# 遍历行列表for line in lines:print(line.strip()) # 去除换行符和空格
-
直接迭代文件对象(推荐逐行读取):
文件对象本身是可迭代的,逐行读取时内存效率最高:with open("test.txt", "r", encoding="utf-8") as f:for line in f: # 每次读取一行,自动处理指针print(line.strip())
总结:
- 大文件优先使用
for line in f
或readline()
,避免占用过多内存。 - 小文件可使用
read()
或readlines()
一次性读取。
73. 什么是上下文管理器(with
语句)?它的优势是什么?
上下文管理器(Context Manager) 是一种用于管理资源(如文件、网络连接、数据库连接)的机制,通过with
语句实现,确保资源在使用后被正确释放(即使发生异常)。
基本语法:
with 资源获取表达式 as 变量:# 使用资源的代码块
文件操作示例:
# 使用with语句操作文件(自动关闭)
with open("test.txt", "r") as f:content = f.read()
# 代码块结束后,文件自动关闭,无需手动调用f.close()
上下文管理器的优势:
-
自动释放资源
无论代码块是否正常执行或发生异常,资源都会被自动释放(如文件关闭、连接断开),避免资源泄漏。# 不使用with的风险(可能忘记关闭文件) f = open("test.txt", "r") content = f.read() # f.close() # 若忘记调用,文件可能保持打开状态
-
简化代码
无需显式编写try...finally
块来确保资源释放,代码更简洁。# 等价的try...finally写法 f = open("test.txt", "r") try:content = f.read() finally:f.close() # 确保关闭
-
支持多个资源同时管理
可在一个with
语句中处理多个资源,按顺序获取并逆序释放。with open("a.txt", "r") as f1, open("b.txt", "w") as f2:content = f1.read()f2.write(content)
自定义上下文管理器:
通过实现__enter__()
和__exit__()
方法可自定义上下文管理器:
class MyContext:def __enter__(self):print("进入上下文:获取资源")return "资源对象" # 赋值给as后的变量def __exit__(self, exc_type, exc_val, exc_tb):print("退出上下文:释放资源")# 处理异常(若返回True则抑制异常)return Falsewith MyContext() as res:print(f"使用{res}")
# 输出:
# 进入上下文:获取资源
# 使用资源对象
# 退出上下文:释放资源
常见应用场景:
- 文件操作(最常用)
- 数据库连接
- 网络请求
- 线程锁
with
语句是Python中处理资源的最佳实践,既安全又简洁。
74. 如何写入文件内容?
在Python中,写入文件需先以写入模式(如w
、a
、r+
等)打开文件,再通过文件对象的写入方法(write()
、writelines()
)写入内容。
常用写入方法:
write(string)
:写入字符串(文本模式)或字节串(二进制模式),返回写入的字符数(或字节数)。writelines(iterable)
:写入可迭代对象(如列表)中的所有元素,元素需为字符串(或字节串),不自动添加换行符。
示例:
-
基本写入(覆盖模式
w
):# 以只写模式打开,若文件存在则覆盖内容 with open("output.txt", "w", encoding="utf-8") as f:# 写入单行f.write("Hello, World!\n") # \n手动添加换行# 写入多行f.write("这是第二行\n")f.write("这是第三行\n")
output.txt
内容:Hello, World! 这是第二行 这是第三行
-
追加写入(
a
模式):# 以追加模式打开,新内容添加到文件末尾 with open("output.txt", "a", encoding="utf-8") as f:f.write("这是追加的一行\n")
output.txt
内容变为:Hello, World! 这是第二行 这是第三行 这是追加的一行
-
使用
writelines()
写入列表:lines = ["第一行\n", "第二行\n", "第三行\n"] with open("lines.txt", "w", encoding="utf-8") as f:f.writelines(lines) # 写入列表中的所有字符串
-
读写模式(
r+
)插入内容:# 打开已存在的文件,读取并插入内容 with open("output.txt", "r+", encoding="utf-8") as f:content = f.read() # 先读取全部内容f.seek(0) # 指针移回开头f.write("在开头插入的内容\n" + content) # 覆盖写入(插入到开头)
-
二进制写入:
# 写入二进制文件(如图片、音频) data = b"Binary data: \x00\x01\x02" # 字节串 with open("binary.bin", "wb") as f:f.write(data)
注意:
- 文本模式下,
write()
接收字符串,需注意编码(通过encoding
参数指定)。 - 二进制模式下,
write()
接收字节串(前缀b
的字符串),不涉及编码。 - 写入后内容可能缓存在内存中,可通过
f.flush()
强制刷新到磁盘,或关闭文件时自动刷新。
75. 如何处理CSV文件?(使用csv
模块或pandas
)
CSV(Comma-Separated Values)是一种常用的表格数据格式,Python中可通过csv
标准库或pandas
库处理。
1. 使用csv
模块(标准库)
csv
模块提供基础的CSV读写功能,适合简单场景。
读取CSV文件:
import csv# 读取CSV(默认逗号分隔)
with open("data.csv", "r", encoding="utf-8") as f:reader = csv.reader(f) # 创建reader对象header = next(reader) # 获取表头(第一行)print("表头:", header)# 遍历数据行for row in reader:print("数据行:", row)# 读取为字典(表头为键)
with open("data.csv", "r", encoding="utf-8") as f:reader = csv.DictReader(f) # DictReader按表头映射为字典for row in reader:print(row["姓名"], row["年龄"]) # 通过表头访问
写入CSV文件:
import csv# 写入CSV
data = [["姓名", "年龄", "城市"],["Alice", 30, "北京"],["Bob", 25, "上海"]
]with open("output.csv", "w", encoding="utf-8", newline="") as f:writer = csv.writer(f) # 创建writer对象writer.writerows(data) # 写入多行# 按字典写入(指定表头)
with open("dict_output.csv", "w", encoding="utf-8", newline="") as f:fieldnames = ["姓名", "年龄", "城市"]writer = csv.DictWriter(f, fieldnames=fieldnames)writer.writeheader() # 写入表头writer.writerow({"姓名": "Charlie", "年龄": 35, "城市": "广州"})writer.writerows([{"姓名": "David", "年龄": 28, "城市": "深圳"},{"姓名": "Eve", "年龄": 22, "城市": "杭州"}])
2. 使用pandas
库(第三方库)
pandas
提供更强大的CSV处理功能,适合复杂数据分析场景,需先安装:
pip install pandas
读取CSV文件:
import pandas as pd# 读取CSV为DataFrame(表格数据结构)
df = pd.read_csv("data.csv")# 查看数据
print("前5行:")
print(df.head()) # 前5行
print("\n表头:", df.columns.tolist()) # 表头列表
print("\n数据类型:")
print(df.dtypes) # 各列数据类型# 按条件筛选
adults = df[df["年龄"] >= 18]
print("\n成年人数据:")
print(adults)
写入CSV文件:
import pandas as pd# 创建DataFrame
data = {"姓名": ["Alice", "Bob", "Charlie"],"年龄": [30, 25, 35],"城市": ["北京", "上海", "广州"]
}
df = pd.DataFrame(data)# 写入CSV
df.to_csv("pandas_output.csv", index=False, encoding="utf-8")
# index=False:不写入行索引
对比:
工具 | 优势 | 劣势 | 适用场景 |
---|---|---|---|
csv 模块 | 标准库,无需安装;轻量灵活。 | 功能简单,需手动处理数据类型;不支持复杂查询。 | 简单读写、小文件、无第三方库依赖时。 |
pandas | 功能强大,支持数据筛选、聚合、类型转换;适合大文件。 | 需要安装;学习成本较高。 | 数据分析、复杂处理、大文件。 |
注意:
- CSV文件可能使用非逗号分隔符(如制表符
\t
),csv
模块可通过delimiter
参数指定,pandas
通过sep
参数指定。 - 处理中文时需指定正确编码(如
utf-8
)。
76. 如何遍历一个目录下的所有文件和子目录?(os.walk()
)
os.walk()
是Python os
模块提供的用于递归遍历目录树的函数,能够便捷地访问指定目录下的所有文件和子目录。
工作原理:
- 接收一个目录路径作为参数,返回一个生成器(generator)。
- 每次迭代生成一个元组
(root, dirs, files)
:root
:当前正在遍历的目录路径。dirs
:当前目录下的子目录名称列表(不包含路径)。files
:当前目录下的文件名称列表(不包含路径)。
示例:
假设有如下目录结构:
data/report.txtlogs/log1.txtlog2.txtimages/photo.jpg
遍历 data
目录:
import os# 遍历目录及其子目录
for root, dirs, files in os.walk("data"):print(f"当前目录: {root}")print(f"子目录: {dirs}")print(f"文件: {files}")print("---")
输出:
当前目录: data
子目录: ['logs', 'images']
文件: ['report.txt']
---
当前目录: data\logs
子目录: []
文件: ['log1.txt', 'log2.txt']
---
当前目录: data\images
子目录: []
文件: ['photo.jpg']
---
实用场景:
-
查找特定类型文件:
# 收集所有.txt文件的完整路径 txt_files = [] for root, dirs, files in os.walk("data"):for file in files:if file.endswith(".txt"):full_path = os.path.join(root, file) # 拼接完整路径txt_files.append(full_path) print("所有TXT文件:", txt_files)
-
统计文件数量:
file_count = 0 for root, dirs, files in os.walk("data"):file_count += len(files) print(f"总文件数: {file_count}") # 输出:4
注意:
os.walk()
会自动递归进入所有子目录,无需手动处理嵌套。- 可通过修改
dirs
列表控制是否遍历某些子目录(如dirs[:] = [d for d in dirs if d != "temp"]
跳过temp
目录)。
77. 如何获取文件的大小、创建时间、修改时间?
在Python中,可通过 os
模块和 pathlib
模块(Python 3.4+)获取文件的元数据,包括大小、创建时间和修改时间。
方法1:使用 os
模块
import os
import timefile_path = "example.txt"# 1. 获取文件大小(字节)
file_size = os.path.getsize(file_path)
print(f"文件大小: {file_size} 字节") # 如:1024 字节# 2. 获取修改时间(时间戳)
modify_time_stamp = os.path.getmtime(file_path)
# 转换为可读时间
modify_time = time.ctime(modify_time_stamp)
print(f"修改时间: {modify_time}") # 如:Wed Jun 12 10:30:45 2024# 3. 获取创建时间(Windows系统有效,Unix系统可能返回最后元数据修改时间)
create_time_stamp = os.path.getctime(file_path)
create_time = time.ctime(create_time_stamp)
print(f"创建时间: {create_time}")
方法2:使用 pathlib
模块(面向对象风格)
from pathlib import Path
import timefile_path = Path("example.txt")# 1. 文件大小
file_size = file_path.stat().st_size
print(f"文件大小: {file_size} 字节")# 2. 修改时间
modify_time = time.ctime(file_path.stat().st_mtime)
print(f"修改时间: {modify_time}")# 3. 创建时间
create_time = time.ctime(file_path.stat().st_ctime)
print(f"创建时间: {create_time}")
关键属性说明:
st_size
:文件大小(字节)。st_mtime
:最后修改时间(时间戳,自1970-01-01 00:00:00 UTC起的秒数)。st_ctime
:在Windows上为创建时间,在Unix上为最后元数据修改时间。st_atime
:最后访问时间(部分系统可能禁用更新以提高性能)。
格式化时间为指定格式:
from datetime import datetimemodify_time = datetime.fromtimestamp(file_path.stat().st_mtime)
print(f"格式化修改时间: {modify_time.strftime('%Y-%m-%d %H:%M:%S')}")
# 输出:2024-06-12 10:30:45
注意:
- 时间戳转换需考虑时区,默认使用本地时区。
- 目录也可通过相同方法获取大小和时间(目录大小为元数据大小,非包含文件总大小)。
78. 如何重命名或删除文件/目录?
Python的 os
模块和 pathlib
模块提供了重命名和删除文件/目录的功能,操作简单但需谨慎(删除操作不可逆)。
1. 重命名文件/目录
使用 os
模块:
import os# 重命名文件
old_file = "old_file.txt"
new_file = "new_file.txt"
os.rename(old_file, new_file) # 若new_file已存在,会被覆盖(Windows)或报错(Unix)# 重命名目录
old_dir = "old_dir"
new_dir = "new_dir"
os.rename(old_dir, new_dir)
使用 pathlib
模块:
from pathlib import Path# 重命名文件
old_file = Path("old_file.txt")
new_file = Path("new_file.txt")
old_file.rename(new_file)# 重命名目录
old_dir = Path("old_dir")
new_dir = Path("new_dir")
old_dir.rename(new_dir)
2. 删除文件/目录
删除文件:
import os
from pathlib import Path# 使用os模块
os.remove("file_to_delete.txt") # 只能删除文件,删除目录会报错# 使用pathlib模块
file = Path("file_to_delete.txt")
file.unlink() # 同os.remove()
删除目录:
os.rmdir()
/Path.rmdir()
:删除空目录。shutil.rmtree()
:删除非空目录(包含所有文件和子目录)。
import os
import shutil
from pathlib import Path# 删除空目录
os.rmdir("empty_dir") # 若目录非空,会报错
Path("empty_dir").rmdir()# 删除非空目录(慎用!)
shutil.rmtree("non_empty_dir") # 递归删除所有内容
示例:安全删除前检查
import os
import shutildef safe_delete(path):if not os.path.exists(path):print(f"{path} 不存在")returnif os.path.isfile(path):os.remove(path)print(f"文件 {path} 已删除")elif os.path.isdir(path):# 检查目录是否为空if len(os.listdir(path)) == 0:os.rmdir(path)print(f"空目录 {path} 已删除")else:# 危险操作:删除非空目录confirm = input(f"确定删除非空目录 {path} 及其内容?(y/n)")if confirm.lower() == "y":shutil.rmtree(path)print(f"目录 {path} 已删除")safe_delete("test.txt")
safe_delete("empty_folder")
safe_delete("full_folder")
注意:
- 重命名时,若目标路径已存在,可能覆盖或报错(取决于操作系统)。
- 删除操作不可逆,尤其是
shutil.rmtree()
会彻底删除目录及内容,务必谨慎。 - 操作前建议检查文件/目录是否存在(
os.path.exists()
或Path.exists()
)。
79. 什么是二进制文件和文本文件?它们的操作有何区别?
文本文件和二进制文件是计算机中两种基本文件类型,其存储格式和操作方式有显著区别:
定义
- 文本文件:以字符编码(如UTF-8、GBK)存储的文件,内容由可打印字符(文字、数字、符号)组成,可被文本编辑器直接阅读(如
.txt
、.py
、.csv
)。 - 二进制文件:以字节(0-255的数值)直接存储数据,内容是计算机可执行的指令或特定格式的二进制数据(如
.png
、.mp3
、.exe
、.zip
),需专用软件解析。
操作区别
特性 | 文本文件 | 二进制文件 |
---|---|---|
打开模式 | 使用 r /w /a 等模式,需指定编码(如 encoding="utf-8" ) | 使用 rb /wb /ab 等模式,无需编码参数 |
数据单位 | 字符(由编码映射的字节序列) | 字节(原始二进制数据) |
读写内容 | 字符串(str 类型) | 字节串(bytes 类型,前缀 b ) |
换行符处理 | 自动转换(如Windows的 \r\n 与Unix的 \n ) | 不处理换行符,按原始字节存储 |
适用场景 | 存储文字信息(文档、代码、配置) | 存储非文字数据(图片、音频、可执行文件) |
示例
- 文本文件操作:
# 写入文本文件
with open("text.txt", "w", encoding="utf-8") as f:f.write("Hello, 世界!\n") # 写入字符串# 读取文本文件
with open("text.txt", "r", encoding="utf-8") as f:content = f.read() # 读取为字符串print(content) # Hello, 世界!
- 二进制文件操作:
# 写入二进制文件
data = b"\x89PNG\r\n\x1a\n..." # 假设是PNG图片的二进制数据(字节串)
with open("image.png", "wb") as f:f.write(data) # 写入字节串# 读取二进制文件
with open("image.png", "rb") as f:binary_data = f.read() # 读取为字节串print(type(binary_data)) # <class 'bytes'>print(binary_data[:10]) # 打印前10个字节
关键区别总结
- 文本文件本质是“字符的序列”,依赖编码规则;二进制文件是“字节的序列”,不依赖编码。
- 错误的模式操作会导致问题(如用文本模式读图片会乱码,用二进制模式读文本可能包含未解码的字节)。
- 转换关系:文本文件 → 字符串(
str
)→ 编码(encode()
)→ 字节串(bytes
)→ 二进制文件。
80. 如何处理大文件(内存无法一次性加载)?
处理大文件(如GB级日志、CSV)时,若一次性加载到内存会导致内存溢出,需采用分批读取或流式处理的方式。
核心原则
- 避免使用
read()
或readlines()
一次性读取全部内容。 - 逐行或分块读取,处理后释放内存。
常用方法
-
文本文件:逐行读取
文件对象是可迭代的,每次迭代返回一行,内存效率高:# 处理大日志文件,统计包含"ERROR"的行数 error_count = 0 with open("large_log.txt", "r", encoding="utf-8") as f:for line in f: # 逐行读取,内存中只保留一行if "ERROR" in line:error_count += 1 print(f"错误行数: {error_count}")
-
二进制文件:分块读取
按固定大小(如4KB、1MB)分块读取,适用于图片、视频等:# 复制大文件(分块读取写入) chunk_size = 4096 # 4KB块 with open("large_file.bin", "rb") as src, open("copy.bin", "wb") as dst:while True:chunk = src.read(chunk_size) # 读取一块if not chunk: # 读取完毕(空字节串)breakdst.write(chunk) # 写入一块
-
CSV文件:分批处理
使用pandas
分块读取大型CSV:import pandas as pd# 每次读取1000行 chunk_size = 1000 total = 0# 分块读取CSV for chunk in pd.read_csv("large_data.csv", chunksize=chunk_size):# 处理当前块(如计算某列总和)total += chunk["value"].sum()print(f"总和: {total}")
-
生成器处理
使用生成器(yield
)封装读取逻辑,进一步控制内存:def read_large_file(file_path, chunk_size=4096):with open(file_path, "r", encoding="utf-8") as f:while True:chunk = f.read(chunk_size) # 按字符数分块if not chunk:breakyield chunk # 生成器逐个返回块# 使用生成器 for chunk in read_large_file("large_text.txt"):# 处理块(如搜索关键词)if "target" in chunk:print("找到目标内容")break
注意事项
- 分块大小需平衡效率(太大占用内存,太小IO频繁),通常设为4KB-1MB。
- 处理行数据时,若行长度超过分块大小,需注意跨块拼接(如日志文件中单行可能很长)。
- 二进制文件分块时需保持块大小一致,避免破坏文件结构。
通过上述方法,可在有限内存中高效处理远超内存容量的大文件。
二、150道Python面试题目录列表
文章序号 | Python面试题150道 |
---|---|
1 | Python面试题及详细答案150道(01-15) |
2 | Python面试题及详细答案150道(16-30) |
3 | Python面试题及详细答案150道(31-40) |
4 | Python面试题及详细答案150道(41-55) |
5 | Python面试题及详细答案150道(56-70) |
6 | Python面试题及详细答案150道(71-80) |
7 | Python面试题及详细答案150道(81-90) |
8 | Python面试题及详细答案150道(91-100) |
9 | Python面试题及详细答案150道(101-115) |
10 | Python面试题及详细答案150道(116-125) |
11 | Python面试题及详细答案150道(126-135) |
12 | Python面试题及详细答案150道(136-150) |