Published on

面试Python

Authors
  • avatar
    Name
    Shelton Ma
    Twitter

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()
# 文件会在退出代码块时自动关闭

9. Python 中的 __init__ 方法的作用是什么?解释下魔法函数

魔法函数: __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 中的 strrepr 方法有什么区别?

__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}