- Published on
面试Python
- Authors
- Name
- Shelton Ma
Python 基础知识
1. 解释 Python 中的 GIL(全局解释器锁)以及它如何影响多线程编程
答案:GIL(Global Interpreter Lock)是 CPython 解释器的一个机制,用于确保在任何时候只有一个线程执行 Python 字节码。它保证了线程安全性,但也限制了多核处理器的并行性。在 I/O 密集型操作中(如文件读写、网络请求),多个线程可以并发运行,但在 CPU 密集型任务(如计算密集型运算)中,GIL 会导致线程并行性受限,因此多个线程并不会在多核 CPU 上获得真正的并行执行。要实现 CPU 密集型任务的并行,通常可以使用多进程(multiprocessing 模块)来绕过 GIL 限制。
2. 在 Python 中,deepcopy 和 copy 的区别是什么?
copy.copy() 是浅拷贝,只复制对象本身的引用,而不复制对象内部嵌套的可变对象。 copy.deepcopy() 是深拷贝,会递归地复制对象及其内部嵌套的所有可变对象。 举个例子:
import copy
a = [[1, 2], [3, 4]]
b = copy.copy(a) # 浅拷贝
c = copy.deepcopy(a) # 深拷贝
a[0][0] = 999
print(b[0][0]) # 输出 999,因为浅拷贝只复制引用
print(c[0][0]) # 输出 1,因为深拷贝复制了独立的副本
3. 什么是列表推导式(List Comprehension),请举例说明其应用
# 生成 1 到 10 的平方数列表
squares = [x ** 2 for x in range(1, 11)]
4. 解释 Python 中的生成器(Generator)和迭代器(Iterator)之间的区别
生成器是通过 yield 关键字定义的,返回一个生成器对象,每次迭代时生成一个新的值。生成器比列表更节省内存,因为它们是懒加载的。 迭代器是实现了 __iter__() 和 __next__()
方法的对象,生成器本质上是迭代器。
5. Python 中的装饰器(Decorator)是什么?举例说明如何使用装饰器
装饰器是一个函数,用于扩展或修改其他函数的行为。通常用于日志、权限检查等场景。
def decorator(func):
def wrapper():
print("Before function call")
func()
print("After function call")
return wrapper
@decorator
def say_hello():
print("Hello!")
6. Python 中如何进行多重继承?如果多个父类有相同的方法,如何解决方法冲突?
Python 支持多重继承,如果多个父类有相同的方法,会按照方法解析顺序(MRO)来决定调用顺序。可以使用 super() 来避免冲突。
class A:
def greet(self):
print("Hello from A")
class B:
def greet(self):
print("Hello from B")
class C(A, B):
def greet(self):
super().greet() # 调用 A 类的方法
print("Hello from C")
7. 解释 Python 中的 lambda 函数的作用及用法
lambda 函数是一个匿名函数,通常用于简短的函数操作。它的语法是 lambda 参数: 表达式。
add = lambda x, y: x + y
print(add(3, 4)) # 输出 7
8. 如何在 Python 中使用 with 语句?它的作用是什么?
with 语句用于处理资源管理(如文件操作、数据库连接等),它确保代码块执行完后自动释放资源。
with open('file.txt', 'r') as f:
content = f.read()
# 文件会在退出代码块时自动关闭
__init__
方法的作用是什么?解释下魔法函数
9. Python 中的 魔法函数: __init__/del/new/cmp...
(创建对象时通过new创建, init初始化), __lt__
会直接用在排序里
10. Python 中的 filter 函数和 map 函数有什么区别
- filter 用于过滤序列中的元素,根据函数的返回值(True 或 False)决定是否保留该元素。
- map 用于将一个函数作用于序列的每一个元素,返回处理后的结果。
# filter 示例
numbers = [1, 2, 3, 4, 5]
even = filter(lambda x: x % 2 == 0, numbers) # 过滤偶数
# map 示例
squares = map(lambda x: x ** 2, numbers) # 将每个元素平方
11. 如何在 Python 中处理异常?
使用 try, except, else, finally 语句来捕获并处理异常。
try:
result = 10 / 0
except ZeroDivisionError:
print("Cannot divide by zero")
else:
print("No errors")
finally:
print("This always runs")
12. Python 中的 str 和 repr 方法有什么区别?
__str__
主要用于将对象转为字符串,目的是为了用户友好显示。 __repr__
主要用于返回对象的官方字符串表示,通常用于调试。
class Person:
def __str__(self):
return f"Person: {self.name}"
def __repr__(self):
return f"Person('{self.name}')"
13. Python垃圾回收机制
Python通过引用计数和垃圾回收(GC)机制来实现内存管理。
Python的最基本的内存管理方式是引用计数
。每个对象都有一个引用计数器,记录着该对象被引用的次数。当一个对象的引用计数为零时,表示该对象没有被引用,可以安全地回收内存。问题:
引用计数有一个局限性,它无法处理循环引用的情况,即两个对象互相引用,导致它们的引用计数永远不会变为零,从而导致内存泄漏。
垃圾回收(GC)
: 分代垃圾回收
手动触发垃圾回收
Flask
1. Flask 中如何处理请求中的表单数据和 JSON 数据?
表单数据:可以通过 request.form 获取,request.form 是一个 MultiDict 对象,包含了所有通过 POST 提交的表单数据。
from flask import Flask, request
app = Flask(__name__)
@app.route('/submit', methods=['POST'])
def submit():
username = request.form['username']
return f"Hello, {username}!"
JSON 数据:通过 request.get_json() 获取请求体中的 JSON 数据,并将其解析为 Python 字典。
from flask import Flask, request
app = Flask(__name__)
@app.route('/json', methods=['POST'])
def json_data():
data = request.get_json()
name = data['name']
return f"Hello, {name}!"
2. Flask 中的 Blueprint 是什么,如何使用它?
Blueprint 是 Flask 提供的一种组织应用代码的方式,可以将应用分割成多个模块,使得代码更加清晰和可维护。通过 Blueprint 可以将不同的视图、路由、静态文件等组织到不同的蓝图中,然后在主应用中注册这些蓝图。
from flask import Flask, Blueprint
# 创建一个蓝图
bp = Blueprint('bp', __name__)
@bp.route('/hello')
def hello():
return "Hello from Blueprint!"
# 创建主应用并注册蓝图
app = Flask(__name__)
app.register_blueprint(bp, url_prefix='/bp')
if __name__ == '__main__':
app.run()
3. Flask 中如何使用 session?它的作用是什么?
session 是 Flask 提供的一种存储客户端数据的方法,数据会保存在浏览器的 cookies 中,并且会在多个请求之间保持状态。
from flask import session
@app.route('/set_session')
def set_session():
session['user'] = 'Alice'
return "Session set!"
@app.route('/get_session')
def get_session():
user = session.get('user', 'Guest')
return f"Hello, {user}!"
4. Flask 中如何处理文件上传?
Flask 提供了 request.files 来处理文件上传。上传的文件可以通过 request.files['file'] 访问。
from flask import request
@app.route('/upload', methods=['POST'])
def upload_file():
file = request.files['file']
file.save(f"./uploads/{file.filename}")
return "File uploaded!"
5. Flask 中如何实现跨域请求(CORS)?
from flask_cors import CORS
from flask import Flask
app = Flask(__name__)
CORS(app)
6. Flask 中如何设置日志?
import logging
from flask import Flask
app = Flask(__name__)
# 设置日志级别
app.logger.setLevel(logging.DEBUG)
@app.route('/')
def hello_world():
app.logger.info('Hello, World!')
return 'Hello, World!'
7. 如何在 Flask 中实现用户认证?
可以通过 Flask-Login 扩展来实现用户认证和会话管理。
from flask_login import LoginManager, UserMixin, login_user
login_manager = LoginManager()
class User(UserMixin):
pass
@login_manager.user_loader
def load_user(user_id):
return User()
# 登录路由
@app.route('/login', methods=['POST'])
def login():
user = User()
login_user(user)
return 'Logged in!'
8. Flask 中如何管理数据库连接
可以使用 Flask-SQLAlchemy 来管理数据库连接。它提供了 ORM 功能和简化的数据库操作。
from flask_sqlalchemy import SQLAlchemy
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///example.db'
db = SQLAlchemy(app)
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(80))
db.create_all() # 创建表
9. Flask 中的 before_request 和 after_request 钩子是什么?
- before_request 会在每个请求处理之前执行,用于进行前置操作。
- after_request 会在每个请求处理之后执行,用于进行后置操作。
@app.before_request
def before_request_func():
print("Before request")
@app.after_request
def after_request_func(response):
print("After request")
return response
10. Flask 中如何使用模板引擎(Jinja2)渲染 HTML 模板?
Flask 使用 Jinja2 作为默认模板引擎,通过 render_template 函数渲染 HTML 文件。
11. Flask 中如何进行单元测试?
Flask 提供了 Flask.testing 模块,可以通过 test_client() 方法进行单元测试。
with app.test_client() as client:
response = client.get('/')
assert response.data == b'Hello, World!'
12. Flask 中如何处理静态文件?
Flask 会自动提供静态文件服务,默认情况下,静态文件存放在 static/ 目录下。
@app.route('/static/<filename>')
def static_file(filename):
return send_from_directory('static', filename)
FastAPI
1. FastAPI 中的 Pydantic 是什么?它如何与请求和响应数据验证相关?
Pydantic 是 FastAPI 的核心数据验证和序列化库。它提供了一种声明式的方式来定义请求和响应体的模型,通过 Python 类型注解来进行数据验证和转换。FastAPI 自动将请求体与 Pydantic 模型进行匹配,并且在请求数据不符合模型时,返回详细的错误响应。
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
# 定义 Pydantic 模型
class User(BaseModel):
name: str
age: int
@app.post("/create-user")
def create_user(user: User):
return {"name": user.name, "age": user.age}
2. FastAPI 中的异步路由与普通路由有何不同?
FastAPI 允许你使用 async 和 await 定义异步路由,这对于处理 I/O 密集型操作(如数据库查询、外部 API 调用等)非常有用。异步路由允许 FastAPI 在等待某个操作完成时,处理其他请求,从而提高应用的并发性能。
from fastapi import FastAPI
import asyncio
app = FastAPI()
@app.get("/async-task")
async def async_task():
await asyncio.sleep(1)
return {"message": "Task completed"}
3. FastAPI 中如何使用路径参数(Path Parameters)?
from fastapi import FastAPI
app = FastAPI()
@app.get("/items/{item_id}")
def read_item(item_id: int):
return {"item_id": item_id}
4. FastAPI 中如何进行请求体(Request Body)的验证?
FastAPI 使用 Pydantic 模型来验证请求体的数据。
from pydantic import BaseModel
from fastapi import FastAPI
app = FastAPI()
class Item(BaseModel):
name: str
price: float
@app.post("/items/")
def create_item(item: Item):
return {"name": item.name, "price": item.price}
5. FastAPI 如何处理查询参数(Query Parameters)?
from fastapi import FastAPI
app = FastAPI()
@app.get("/items/")
def read_items(q: str = None):
return {"q": q}
6. FastAPI 中如何使用依赖注入(Dependency Injection)?
FastAPI 提供了依赖注入机制,可以将函数或类作为依赖注入到其他路径操作中。
from fastapi import FastAPI, Depends
app = FastAPI()
def get_query_param(q: str = None):
return q
@app.get("/")
def read_root(query: str = Depends(get_query_param)):
return {"query": query}