Python面试题及详细答案150道(136-150) -- 网络编程及常见问题篇
《前后端面试题
》专栏集合了前后端各个知识模块的面试题,包括html,javascript,css,vue,react,java,Openlayers,leaflet,cesium,mapboxGL,threejs,nodejs,mangoDB,SQL,Linux… 。
文章目录
- 一、本文面试题目录
- 136. 什么是HTTP协议?常用的HTTP方法有哪些?
- 137. `urllib`和`requests`库的区别是什么?
- 138. 如何使用`socket`模块实现简单的TCP客户端和服务器?
- 139. 什么是RESTful API?如何设计RESTful接口?
- 140. 简述Django的MTV架构。
- 141. Django和Flask的区别是什么?
- 142. 什么是中间件(Middleware)?Django中间件的作用?
- 143. Flask中如何使用蓝图(Blueprint)?
- 144. 如何处理HTTP请求中的Cookie和Session?
- 145. 什么是WebSocket?它与HTTP有何区别?
- 146. 什么是单元测试?如何使用`unittest`或`pytest`进行单元测试?
- 原理说明
- 示例代码
- 1. 使用`unittest`
- 2. 使用`pytest`
- 147. 什么是文档字符串(Docstring)?它的作用是什么?
- 原理说明
- 示例代码
- 148. 如何实现Python代码的打包和分发(如`setup.py`)?
- 原理说明
- 示例代码
- 1. 项目结构
- 2. `setup.py`配置
- 3. 打包与分发步骤
- 149. 解释Python中的垃圾回收机制(GC)。
- 原理说明
- 示例代码
- 150. 你在项目中使用Python解决过哪些实际问题?请举例说明。
- 示例1:数据清洗与分析工具
- 示例2:定时任务监控系统
- 二、150道Python面试题目录列表
一、本文面试题目录
136. 什么是HTTP协议?常用的HTTP方法有哪些?
原理说明:
HTTP(HyperText Transfer Protocol,超文本传输协议)是用于在客户端和服务器之间传输数据的应用层协议,基于TCP/IP通信,采用请求-响应模式,无状态(每次请求独立,不保留上下文)。
常用HTTP方法:
方法 | 作用 | 特点 |
---|---|---|
GET | 请求获取资源 | 幂等(多次请求结果一致),参数在URL中,有长度限制 |
POST | 提交数据到服务器(如表单提交) | 非幂等,参数在请求体中,无长度限制 |
PUT | 全量更新资源 | 幂等,需提供资源完整数据 |
PATCH | 部分更新资源 | 非幂等,仅提供需修改的字段 |
DELETE | 删除指定资源 | 幂等 |
HEAD | 类似GET,但仅返回响应头 | 用于检查资源是否存在或获取元数据 |
OPTIONS | 获取服务器支持的HTTP方法 | 跨域请求时用于预检 |
示例:
- GET请求:
https://api.example.com/users
(获取用户列表) - POST请求:向
https://api.example.com/users
提交{"name":"Alice"}
(创建用户)
137. urllib
和requests
库的区别是什么?
原理说明:
两者都是Python用于HTTP请求的库,urllib
是标准库,requests
是第三方库(需安装),后者API更简洁,功能更丰富。
核心区别:
特性 | urllib | requests |
---|---|---|
所属 | 标准库(无需安装) | 第三方库(需pip install requests ) |
API设计 | 较繁琐(需构造Request 对象) | 简洁(如requests.get() ) |
会话管理 | 需手动处理CookieJar | 内置Session 对象自动维护Cookie |
响应处理 | 需手动解码(如response.read().decode() ) | 自动解码(response.text ) |
异常处理 | 较复杂(需捕获URLError 等) | 统一的RequestException |
支持功能 | 基础HTTP操作 | 支持会话、代理、SSL验证、文件上传等 |
示例对比:
-
GET请求
# urllib from urllib.request import urlopen response = urlopen("https://www.baidu.com") print(response.read().decode('utf-8'))# requests import requests response = requests.get("https://www.baidu.com") print(response.text) # 自动解码
-
带参数的POST请求
# urllib from urllib.request import Request, urlopen from urllib.parse import urlencode data = urlencode({"name": "Alice"}).encode('utf-8') request = Request("https://api.example.com", data=data, method="POST") response = urlopen(request)# requests response = requests.post("https://api.example.com", data={"name": "Alice"})
总结:requests
语法更简洁,推荐用于大多数HTTP请求场景;urllib
适合无第三方库依赖的环境。
138. 如何使用socket
模块实现简单的TCP客户端和服务器?
原理说明:
TCP(Transmission Control Protocol)是面向连接的可靠传输协议,通过三次握手建立连接,四次挥手关闭连接。Python的socket
模块提供了TCP通信的底层接口,可实现客户端和服务器的双向通信。
示例代码:
-
TCP服务器
import socket# 创建TCP套接字(IPv4,TCP) server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)# 绑定IP和端口(空IP表示监听所有网络接口) server_address = ('', 8888) server_socket.bind(server_address)# 监听连接(最大等待队列长度为5) server_socket.listen(5) print("服务器启动,等待连接...")while True:# 接受客户端连接(阻塞)client_socket, client_addr = server_socket.accept()print(f"接收到来自{client_addr}的连接")try:# 接收客户端数据(最多1024字节)data = client_socket.recv(1024)if data:print(f"收到数据:{data.decode('utf-8')}")# 发送响应response = "消息已收到:" + data.decode('utf-8')client_socket.sendall(response.encode('utf-8'))finally:# 关闭客户端连接client_socket.close()print(f"与{client_addr}的连接已关闭")
-
TCP客户端
import socket# 创建TCP套接字 client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)# 连接服务器 server_address = ('localhost', 8888) client_socket.connect(server_address)try:# 发送数据message = "Hello, Server!"client_socket.sendall(message.encode('utf-8'))# 接收响应data = client_socket.recv(1024)print(f"收到服务器响应:{data.decode('utf-8')}") finally:# 关闭连接client_socket.close()
通信流程:
- 服务器:创建套接字 → 绑定端口 → 监听 → 接受连接 → 收发数据 → 关闭连接。
- 客户端:创建套接字 → 连接服务器 → 收发数据 → 关闭连接。
注意:实际应用中需处理异常(如连接中断)和多客户端并发(如使用多线程)。
139. 什么是RESTful API?如何设计RESTful接口?
原理说明:
RESTful API是一种基于REST(Representational State Transfer)架构风格设计的API,通过HTTP方法对资源进行操作,强调无状态、资源导向和统一接口。
核心设计原则:
- 资源导向:用URL表示资源(如
/users
表示用户列表),而非动作(避免/getUsers
)。 - 使用HTTP方法表达操作:
- GET:查询资源(
/users/1
获取ID=1的用户) - POST:创建资源(
/users
创建新用户) - PUT/PATCH:更新资源(
/users/1
更新用户信息) - DELETE:删除资源(
/users/1
删除用户)
- GET:查询资源(
- 无状态:服务器不存储客户端状态,每次请求需包含所有必要信息。
- 返回合适的状态码:如200(成功)、201(创建成功)、404(资源不存在)、500(服务器错误)。
- 使用JSON作为数据交换格式。
设计示例:
接口 | HTTP方法 | 功能 | 响应状态码 |
---|---|---|---|
/api/users | GET | 获取所有用户 | 200 OK |
/api/users/1 | GET | 获取ID=1的用户 | 200 OK / 404 Not Found |
/api/users | POST | 创建新用户(请求体含用户数据) | 201 Created |
/api/users/1 | PUT | 全量更新用户1 | 200 OK / 404 |
/api/users/1 | PATCH | 部分更新用户1(如仅改姓名) | 200 OK / 404 |
/api/users/1 | DELETE | 删除用户1 | 204 No Content / 404 |
示例请求与响应:
- 创建用户(POST
/api/users
):
请求体:{"name": "Alice", "age": 25}
响应:{"id": 1, "name": "Alice", "age": 25}
(状态码201)
140. 简述Django的MTV架构。
原理说明:
Django是Python的Web框架,采用MTV(Model-Template-View)架构,是MVC(Model-View-Controller)的变种,目的是分离数据、界面和业务逻辑。
MTV各组件及作用:
-
Model(模型)
- 负责数据管理和数据库交互,对应数据库表结构。
- 使用Django ORM定义,自动映射到数据库,无需编写SQL。
- 示例:
# models.py from django.db import models class Book(models.Model):title = models.CharField(max_length=100)author = models.CharField(max_length=50)publish_date = models.DateField()
-
Template(模板)
- 负责用户界面渲染,定义HTML页面结构和展示逻辑。
- 支持模板继承、变量替换、条件判断等,分离业务逻辑和展示。
- 示例(
book_list.html
):<h1>图书列表</h1> <ul>{% for book in books %}<li>{{ book.title }} - {{ book.author }}</li>{% endfor %} </ul>
-
View(视图)
- 负责处理用户请求、业务逻辑(如数据查询、验证),连接Model和Template。
- 接收请求,调用Model获取数据,传递给Template渲染后返回响应。
- 示例:
# views.py from django.shortcuts import render from .models import Book def book_list(request):books = Book.objects.all() # 从Model获取数据return render(request, 'book_list.html', {'books': books}) # 传递给Template
工作流程:
- 用户发送HTTP请求到Django服务器。
- URL路由系统将请求分发到对应的View。
- View调用Model获取或处理数据。
- View将数据传递给Template,生成HTML响应。
- 响应返回给用户。
MTV架构通过分离关注点,使代码更易维护、扩展和测试。
141. Django和Flask的区别是什么?
原理说明:
Django和Flask都是Python主流Web框架,但设计理念不同:Django是“全栈框架”(内置丰富功能),Flask是“微框架”(轻量灵活,需手动扩展)。
核心区别对比:
特性 | Django | Flask |
---|---|---|
定位 | 全栈框架(内置完整解决方案) | 微框架(轻量,按需扩展) |
内置功能 | ORM、Admin后台、表单验证、用户认证、模板引擎、路由等 | 仅核心功能(路由、模板),其他需通过扩展(如Flask-SQLAlchemy ) |
灵活性 | 较低(遵循Django规范) | 较高(可自由选择组件) |
学习曲线 | 较陡(功能多,概念复杂) | 较平缓(入门简单) |
适用场景 | 大型复杂项目(如电商、CMS) | 小型应用、API服务、快速原型开发 |
模板引擎 | 内置Django Template | 依赖Jinja2(需单独安装) |
扩展方式 | 内置功能为主,第三方插件为辅 | 高度依赖第三方扩展 |
示例对比:
-
创建简单页面
# Django(需配置项目、应用、URL) # views.py from django.http import HttpResponse def hello(request):return HttpResponse("Hello, Django!")# Flask(单文件即可) from flask import Flask app = Flask(__name__) @app.route('/') def hello():return "Hello, Flask!" if __name__ == '__main__':app.run()
-
数据库操作
# Django(内置ORM) from django.db import models class User(models.Model):name = models.CharField(max_length=50) user = User(name="Alice") user.save() # 自动写入数据库# Flask(需扩展Flask-SQLAlchemy) from flask_sqlalchemy import SQLAlchemy app = Flask(__name__) app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///test.db' db = SQLAlchemy(app) class User(db.Model):id = db.Column(db.Integer, primary_key=True)name = db.Column(db.String(50)) db.create_all() user = User(name="Alice") db.session.add(user) db.session.commit()
总结:Django适合需要快速开发且功能全面的项目,Flask适合追求灵活和轻量的场景。
142. 什么是中间件(Middleware)?Django中间件的作用?
原理说明:
中间件是Web框架中位于请求和响应之间的处理层,用于在全局范围内处理请求和响应(如身份验证、日志记录、跨域处理)。Django中间件通过钩子函数介入请求-响应生命周期的各个阶段。
Django中间件的作用:
- 预处理请求:在视图函数执行前处理请求(如验证Token、设置语言)。
- 后处理响应:在响应返回客户端前处理(如添加响应头、压缩数据)。
- 全局异常处理:捕获视图函数抛出的异常,返回统一错误响应。
- 日志记录:记录所有请求的URL、耗时、状态码等信息。
Django中间件工作流程:
请求 → 中间件process_request
→ URL路由 → 中间件process_view
→ 视图函数 → 中间件process_template_response
(若有) → 中间件process_response
→ 响应客户端。
自定义中间件示例:
# myapp/middleware.py
class SimpleMiddleware:def __init__(self, get_response):self.get_response = get_response # 保存下一个中间件/视图的引用def __call__(self, request):# 1. 请求到达视图前执行(process_request)print(f"请求URL:{request.path}")start_time = time.time()# 调用下一个中间件或视图response = self.get_response(request)# 2. 响应返回客户端前执行(process_response)duration = time.time() - start_timeprint(f"请求耗时:{duration:.2f}秒")# 添加自定义响应头response["X-Request-Duration"] = f"{duration:.2f}s"return responsedef process_exception(self, request, exception):# 3. 捕获视图抛出的异常print(f"发生异常:{str(exception)}")# 返回自定义错误响应return HttpResponse("服务器内部错误", status=500)
启用中间件:
在settings.py
的MIDDLEWARE
列表中添加路径:
MIDDLEWARE = [# ... 其他中间件 ...'myapp.middleware.SimpleMiddleware',
]
内置中间件示例:
django.middleware.csrf.CsrfViewMiddleware
:处理CSRF防护。django.contrib.auth.middleware.AuthenticationMiddleware
:管理用户认证。
143. Flask中如何使用蓝图(Blueprint)?
原理说明:
蓝图(Blueprint)是Flask中用于模块化组织路由、视图和静态资源的工具,可将大型应用拆分为多个子模块(如用户模块、商品模块),便于维护。
蓝图的作用:
- 拆分应用功能,实现代码分离。
- 共享模板和静态文件。
- 延迟注册(可在应用初始化后注册蓝图)。
使用示例:
-
创建蓝图(
auth.py
,用户认证模块)from flask import Blueprint, render_template, redirect, url_for# 创建蓝图('auth'为蓝图名称,__name__为模块名) auth_bp = Blueprint('auth', __name__, url_prefix='/auth') # 路由前缀# 定义蓝图路由 @auth_bp.route('/login') def login():return render_template('auth/login.html') # 模板默认查找templates/auth/目录@auth_bp.route('/logout') def logout():return redirect(url_for('auth.login')) # 生成带前缀的URL
-
创建主应用并注册蓝图(
app.py
)from flask import Flask from auth import auth_bp # 导入蓝图app = Flask(__name__)# 注册蓝图(所有路由会自动添加/auth前缀) app.register_blueprint(auth_bp)# 主应用路由 @app.route('/') def index():return "首页"if __name__ == '__main__':app.run()
-
目录结构
myapp/ ├── app.py # 主应用 ├── auth.py # 认证蓝图 └── templates/├── index.html # 主应用模板└── auth/ # 蓝图模板目录└── login.html
访问路由:
- 蓝图路由:
/auth/login
(对应auth_bp.route('/login')
) - 主应用路由:
/
(对应app.route('/')
)
高级用法:
- 蓝图可拥有独立的静态文件目录(
static_folder
参数)。 - 可通过
url_for('蓝图名.视图函数名')
生成蓝图路由URL。
蓝图是Flask构建大型应用的核心工具,通过模块化组织使代码结构更清晰。
144. 如何处理HTTP请求中的Cookie和Session?
原理说明:
Cookie和Session都是用于在客户端和服务器之间保存状态的机制(因HTTP无状态),但存储位置和安全性不同:
- Cookie:存储在客户端(浏览器),由服务器通过响应头
Set-Cookie
设置,每次请求自动携带。 - Session:存储在服务器,客户端仅保存Session ID(通常通过Cookie传递),更安全。
处理方法示例:
-
使用Flask处理Cookie和Session
from flask import Flask, make_response, request, sessionapp = Flask(__name__) app.secret_key = 'secret_key_for_session' # Session需配置密钥(加密用)# 处理Cookie @app.route('/set_cookie') def set_cookie():response = make_response("Cookie已设置")# 设置Cookie(键、值、过期时间(秒))response.set_cookie('username', 'Alice', max_age=3600)return response@app.route('/get_cookie') def get_cookie():# 获取Cookie(默认None)username = request.cookies.get('username')return f"Cookie中的用户名:{username}"# 处理Session @app.route('/set_session') def set_session():# 设置Session(自动加密存储在服务器)session['user_id'] = 123session['username'] = 'Alice'return "Session已设置"@app.route('/get_session') def get_session():# 获取Sessionuser_id = session.get('user_id')username = session.get('username')return f"Session:用户ID={user_id},用户名={username}"@app.route('/logout') def logout():# 清除Sessionsession.pop('user_id', None)session.pop('username', None)return "已退出登录"
-
使用Django处理Cookie和Session
# Django视图 from django.http import HttpResponse# 处理Cookie def set_cookie(request):response = HttpResponse("Cookie已设置")response.set_cookie('username', 'Bob', max_age=3600)return responsedef get_cookie(request):username = request.COOKIES.get('username')return HttpResponse(f"Cookie中的用户名:{username}")# 处理Session(Django默认存储在数据库,可配置为Redis等) def set_session(request):request.session['user_id'] = 456request.session['username'] = 'Bob'return HttpResponse("Session已设置")def get_session(request):user_id = request.session.get('user_id')username = request.session.get('username')return HttpResponse(f"Session:用户ID={user_id},用户名={username}")
安全注意事项:
- Cookie存储在客户端,敏感信息(如密码)不应存于Cookie。
- Session需使用密钥加密(如Flask的
secret_key
),防止篡改。 - 重要Cookie可设置
secure=True
(仅HTTPS传输)和httpOnly=True
(禁止JS访问,防XSS)。
145. 什么是WebSocket?它与HTTP有何区别?
原理说明:
WebSocket是一种在单个TCP连接上实现全双工(双向)通信的协议,允许客户端和服务器实时交换数据,适合实时应用(如聊天、股票行情)。
与HTTP的区别:
特性 | HTTP | WebSocket |
---|---|---|
连接方式 | 单向请求-响应(客户端主动请求,服务器被动响应) | 双向持久连接(客户端和服务器可随时发送数据) |
连接状态 | 无状态(每次请求独立) | 有状态(连接建立后保持打开) |
通信效率 | 低(每次请求需携带完整HTTP头) | 高(连接建立后仅传输数据,无冗余头) |
适用场景 | 普通Web页面、API请求(非实时) | 实时通信(如聊天、实时通知、游戏) |
协议标识 | http:// 或https:// | ws:// 或wss:// (加密) |
Python中使用WebSocket示例(websockets
库):
-
安装库
pip install websockets
-
WebSocket服务器
import asyncio import websockets# 处理客户端连接 async def handle_client(websocket):# 接收客户端消息async for message in websocket:print(f"收到消息:{message}")# 发送响应(双向通信)response = f"服务器已收到:{message}"await websocket.send(response)# 启动服务器 start_server = websockets.serve(handle_client, "localhost", 8765) asyncio.get_event_loop().run_until_complete(start_server) asyncio.get_event_loop().run_forever()
-
WebSocket客户端
import asyncio import websocketsasync def send_message():# 连接服务器async with websockets.connect("ws://localhost:8765") as websocket:# 发送消息message = "Hello, WebSocket!"await websocket.send(message)# 接收响应response = await websocket.recv()print(f"收到响应:{response}")asyncio.get_event_loop().run_until_complete(send_message())
工作流程:
- 客户端通过HTTP握手请求升级协议(
Upgrade: websocket
)。 - 服务器同意后,HTTP连接升级为WebSocket连接。
- 双方通过该连接实时双向通信,直到一方关闭连接。
WebSocket解决了HTTP在实时通信场景下的低效问题,是构建实时Web应用的首选协议。
146. 什么是单元测试?如何使用unittest
或pytest
进行单元测试?
原理说明
- 单元测试:是对软件中最小可测试单元(如函数、方法、类)进行的独立验证,目的是确保每个单元能按预期工作。
- 作用:提前发现bug、便于代码重构、保障代码质量。
- 常用框架:
unittest
:Python内置的单元测试框架,灵感来自Java的JUnit,支持断言、测试用例组织、测试套件等。pytest
:第三方框架,语法更简洁,支持unittest
兼容的用例,还提供更丰富的功能(如参数化、 fixtures)。
示例代码
1. 使用unittest
# 待测试的函数
def add(a, b):return a + bdef is_even(n):return n % 2 == 0# 测试用例
import unittestclass TestMathFunctions(unittest.TestCase):# 测试前执行(可选)def setUp(self):print("开始测试...")# 测试add函数def test_add(self):self.assertEqual(add(2, 3), 5) # 断言相等self.assertEqual(add(-1, 1), 0)# 测试is_even函数def test_is_even(self):self.assertTrue(is_even(4)) # 断言为Trueself.assertFalse(is_even(7)) # 断言为Falseself.assertRaises(TypeError, is_even, "string") # 断言抛出异常# 测试后执行(可选)def tearDown(self):print("测试结束...")if __name__ == "__main__":unittest.main() # 运行测试
2. 使用pytest
需先安装:pip install pytest
# 待测试的函数(同上)
def add(a, b):return a + bdef is_even(n):return n % 2 == 0# 测试用例(pytest无需继承类,函数名以test_开头即可)
def test_add():assert add(2, 3) == 5 # 直接使用assert断言assert add(-1, 1) == 0def test_is_even():assert is_even(4) is Trueassert is_even(7) is Falsewith pytest.raises(TypeError): # 断言抛出异常is_even("string")
运行方式:命令行执行pytest 文件名.py -v
(-v
显示详细信息)。
147. 什么是文档字符串(Docstring)?它的作用是什么?
原理说明
- 文档字符串(Docstring):是位于函数、类、模块开头的字符串,用于解释其功能、参数、返回值、示例等信息。
- 格式:通常用三重引号(
"""
)包裹,支持单行和多行。 - 作用:
- 提高代码可读性,方便其他开发者理解代码用途。
- 可通过
__doc__
属性或help()
函数获取文档信息。 - 支持自动生成文档工具(如Sphinx、pdoc)。
示例代码
def calculate_area(radius):"""计算圆的面积。参数:radius (float): 圆的半径,必须为正数。返回:float: 圆的面积(π * radius²)。异常:ValueError: 当半径为负数或非数字时抛出。示例:>>> calculate_area(2)12.566370614359172"""if not isinstance(radius, (int, float)):raise ValueError("半径必须是数字")if radius <= 0:raise ValueError("半径必须为正数")return 3.1415926535 * radius ** 2# 获取文档字符串
print(calculate_area.__doc__) # 打印完整文档
help(calculate_area) # 更友好的格式显示文档
148. 如何实现Python代码的打包和分发(如setup.py
)?
原理说明
- 打包:将Python代码、依赖、配置文件等整理成标准格式(如
.tar.gz
、.whl
),便于安装和分发。 - 分发渠道:常用PyPI(Python Package Index),用户可通过
pip install
安装。 - 核心文件:
setup.py
:打包配置脚本,定义包名、版本、依赖等。setup.cfg
:补充配置(可选)。MANIFEST.in
:指定需要打包的非代码文件(如文档、数据)。
示例代码
1. 项目结构
my_package/
├── my_package/ # 包目录
│ ├── __init__.py
│ └── utils.py # 功能模块
├── setup.py # 打包配置
└── README.md # 说明文档
2. setup.py
配置
from setuptools import setup, find_packagessetup(name="my_package", # 包名(PyPI上需唯一)version="0.1.0", # 版本号(遵循语义化版本)author="Your Name",author_email="your@email.com",description="A sample Python package",long_description=open("README.md").read(), # 长描述(通常来自README)long_description_content_type="text/markdown",url="https://github.com/yourusername/my_package", # 项目地址packages=find_packages(), # 自动发现包install_requires=[ # 依赖列表"requests>=2.25.0","numpy>=1.19.0"],classifiers=[ # 分类信息(便于PyPI检索)"Programming Language :: Python :: 3","License :: OSI Approved :: MIT License","Operating System :: OS Independent",],python_requires=">=3.6", # 支持的Python版本
)
3. 打包与分发步骤
# 生成源码包和wheel包
python setup.py sdist bdist_wheel# 安装到本地(开发模式,修改代码无需重新安装)
pip install -e .# 上传到PyPI(需先注册账号,安装twine工具)
pip install twine
twine upload dist/* # 输入PyPI账号密码
149. 解释Python中的垃圾回收机制(GC)。
原理说明
- 垃圾回收(GC):Python自动管理内存的机制,用于回收不再使用的对象所占用的内存,避免内存泄漏。
- 核心算法:
- 引用计数:每个对象有一个引用计数器,当引用数为0时,对象被立即回收。
- 触发引用计数减少的情况:变量赋值给其他对象、函数执行结束局部变量销毁、对象从容器中移除等。
- 标记-清除:解决循环引用问题(如两个对象互相引用,引用计数不为0但已无用)。
- 标记:遍历所有可达对象(从根对象出发能访问到的对象),标记为“存活”。
- 清除:未被标记的对象被回收。
- 分代回收:基于“存活越久的对象越不可能被回收”的假设,将对象分为3代(0、1、2)。
- 新对象放入0代,回收频率最高;存活的对象晋升到更高代,回收频率降低。
- 引用计数:每个对象有一个引用计数器,当引用数为0时,对象被立即回收。
示例代码
import gc# 查看GC是否启用(默认启用)
print(gc.isenabled()) # 输出: True# 禁用GC(仅调试用)
gc.disable()
# 手动触发GC
gc.collect()
# 启用GC
gc.enable()# 循环引用示例(引用计数无法回收)
class Node:def __init__(self):self.next = None# 创建循环引用
a = Node()
b = Node()
a.next = b
b.next = a# 删除引用(此时a和b的引用计数仍为1,因互相引用)
del a
del b# 手动回收循环引用的对象
gc.collect()
print(gc.garbage) # 输出回收的对象列表(通常为空,因已被清理)
- 注意:Python的GC机制几乎无需手动干预,但可通过
gc
模块调整参数(如回收阈值)或强制回收。
150. 你在项目中使用Python解决过哪些实际问题?请举例说明。
示例1:数据清洗与分析工具
- 问题:某电商平台需要从多个Excel表格中提取销售数据,清洗重复值、缺失值,并生成月度销售报表。
- 解决方案:
- 使用
pandas
读取Excel文件,合并多表数据。 - 用
pandas
的drop_duplicates()
去重,fillna()
填充缺失值。 - 用
matplotlib
/seaborn
绘制销量趋势图、品类占比图。 - 封装成脚本,支持命令行传入文件路径,自动输出清洗后的数据和报表。
- 使用
import pandas as pd
import matplotlib.pyplot as pltdef clean_and_analyze(file_paths):# 合并数据dfs = [pd.read_excel(path) for path in file_paths]combined = pd.concat(dfs, ignore_index=True)# 清洗数据combined = combined.drop_duplicates(subset=["订单号"])combined["销售额"] = combined["销售额"].fillna(0)# 分析:月度销售额combined["订单日期"] = pd.to_datetime(combined["订单日期"])combined["月份"] = combined["订单日期"].dt.to_period("M")monthly_sales = combined.groupby("月份")["销售额"].sum()# 绘图monthly_sales.plot(kind="bar")plt.title("月度销售额趋势")plt.savefig("monthly_sales.png")# 保存清洗后的数据combined.to_excel("cleaned_sales.xlsx", index=False)return monthly_sales# 使用示例
if __name__ == "__main__":import sysfile_paths = sys.argv[1:] # 从命令行接收文件路径clean_and_analyze(file_paths)
示例2:定时任务监控系统
- 问题:某系统需要定时检查多个服务的可用性(如HTTP接口、数据库连接),异常时发送邮件报警。
- 解决方案:
- 用
schedule
库实现定时任务(如每5分钟执行一次检查)。 - 用
requests
检查HTTP接口状态,pymysql
检查数据库连接。 - 用
smtplib
发送报警邮件,包含异常详情。
- 用
import schedule
import time
import requests
import pymysql
import smtplib
from email.mime.text import MIMEText# 配置
SERVICES = {"API服务": "https://api.example.com/health","数据库": {"host": "db.example.com", "user": "admin", "password": "xxx"}
}
ALERT_EMAIL = "admin@example.com"def send_alert(message):"""发送报警邮件"""msg = MIMEText(message)msg["Subject"] = "服务异常报警"msg["From"] = "monitor@example.com"msg["To"] = ALERT_EMAILwith smtplib.SMTP("smtp.example.com", 587) as server:server.starttls()server.login("monitor@example.com", "password")server.send_message(msg)def check_service():"""检查服务可用性"""for name, config in SERVICES.items():if isinstance(config, str): # HTTP服务try:response = requests.get(config, timeout=10)if response.status_code != 200:raise Exception(f"状态码异常: {response.status_code}")except Exception as e:send_alert(f"{name}异常: {str(e)}")else: # 数据库服务try:conn = pymysql.connect(**config, timeout=10)conn.close()except Exception as e:send_alert(f"{name}异常: {str(e)}")# 定时任务:每5分钟检查一次
schedule.every(5).minutes.do(check_service)# 启动监控
while True:schedule.run_pending()time.sleep(1)
- 效果:实现了自动化监控,减少人工干预,及时发现并处理服务故障。
二、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) |