python八股文汇总(持续更新版)

python装饰器

一、装饰器是什么?

装饰器是Python中一种"化妆师",它能在不修改原函数代码的前提下,给函数动态添加新功能

  • 本质:一个接收函数作为参数,并返回新函数的工具。
  • 作用:像给手机贴膜,既保护屏幕(原函数),又新增防摔功能(装饰逻辑)。

二、核心原理
  1. 函数是"对象":Python中函数可以像变量一样传递,这是装饰器的基础。
  2. 闭包机制:装饰器通过嵌套函数(闭包)保留原函数,并包裹新功能。

工作流程

  1. 你调用被装饰的函数(如hello())。
  2. Python实际执行的是装饰器加工后的新函数。
  3. 新函数先执行装饰器添加的逻辑(如权限检查),再执行原函数。

三、常见用途

场景

作用

生活类比

权限验证

检查用户是否登录再执行函数

进小区前刷卡(装饰器是门禁系统)

日志记录

自动记录函数调用时间和参数

飞机黑匣子(自动记录飞行数据)

性能统计

计算函数运行耗时

跑步时用手表计时

缓存结果

避免重复计算(如@lru_cache

备忘录(记下答案直接复用)


四、两种实现方式
  1. 函数式装饰器
    • 最常用,通过嵌套函数实现。
    • 示例:给函数添加"呼叫提醒"功能
def remind_call(func): def wrapper(): print("【提醒】开始打电话...") func() # 执行原打电话函数 print("【提醒】通话结束") return wrapper @remind_call def call_friend(): print("正在和好友通话中...") call_friend()

输出:

【提醒】开始打电话... 正在和好友通话中... 【提醒】通话结束
  1. 类装饰器
    • 通过实现__call__方法让类能像函数一样调用。
    • 适合需要维护状态的场景(如重试计数器)。

五、需要注意的坑
  1. 原函数信息丢失
    • 直接使用装饰器会导致help(func)显示的是wrapper函数的信息。
    • 解决:用functools.wraps装饰wrapper函数。
  1. 装饰顺序影响
    • 多个装饰器从下往上执行:
@decorator1 # 最后执行 @decorator2 # 先执行 def func(): pass
  1. 带参数的装饰器
    • 需要三层嵌套函数,最外层接收装饰器参数。

六、现实世界类比
  1. 快递打包
    • 原函数 = 商品
    • 装饰器 = 打包服务(先加泡沫纸,再贴快递单)
    • @打包后的商品功能不变,但多了运输保护。
  1. 游戏装备
    • 原函数 = 游戏角色
    • @穿装备后角色攻击力提升,但角色代码未修改。

七、为什么用装饰器?
  1. 避免重复代码(如所有函数都要加日志时)
  2. 保持纯净(不修改原函数,降低耦合)
  3. 灵活组合(像乐高积木一样叠加功能)

一句话总结:装饰器是Python的"功能外挂",用@符号轻松实现代码增强!

Python的深拷贝和浅拷贝

1. 基本概念

类型

特点

适用场景

浅拷贝

只复制对象本身,不复制内部的子对象

简单对象(如列表嵌套不深)

深拷贝

递归复制对象及其所有子对象

复杂嵌套对象(如多层字典/列表)

2. 核心区别
  • 浅拷贝:像给房子拍照片,只复制了外观(顶层结构),房间里的家具(子对象)还是同一套。
  • 深拷贝:连房子带家具全部克隆一份,新旧对象完全独立。
3. 技术实现
(1) 浅拷贝方法
import copy a = [1, [2, 3]] b = copy.copy(a) # 或 a.copy() / list(a) / slice[:]
  • 效果
    • 修改 a[0](不可变类型)不影响 b
    • 修改 a[1][0](可变子对象)会影响 b
(2) 深拷贝方法
c = copy.deepcopy(a)
  • 效果
    • 无论修改 a 的哪一层,c 都完全不受影响
4. 通俗例子
场景1:合租公寓(浅拷贝)
  • 你(a)和室友(b)共用客厅的冰箱(子对象)。
  • 你往冰箱里放啤酒 → 室友也能看到这些啤酒。
  • 但你换了自己的床单(顶层不可变项) → 室友的床单不变。
场景2:买新房(深拷贝)
  • 开发商按样板房(a)给你建了完全一样的房子(c)。
  • 你在新房砸墙 → 样板房毫无影响。
  • 样板房换家具 → 你的新房也不变。
5. 验证实验
import copy # 原始对象(含可变子对象) original = [1, {'name': 'Alice'}, [3, 4]] # 浅拷贝 shallow = copy.copy(original) # 深拷贝 deep = copy.deepcopy(original) # 修改原始对象的子对象 original[1]['name'] = 'Bob' original[2].append(5) print("原始对象:", original) # [1, {'name': 'Bob'}, [3, 4, 5]] print("浅拷贝:", shallow) # [1, {'name': 'Bob'}, [3, 4, 5]] (受影响) print("深拷贝:", deep) # [1, {'name': 'Alice'}, [3, 4]] (不受影响)
6. 特殊注意事项
  1. 不可变类型(数字/字符串/元组)
    • 深浅拷贝无区别(因为本身不能修改)
    • 示例:a = (1, [2]); b = copy.copy(a) → 修改 a[1] 仍会影响 b
  1. 自定义对象
    • 需实现 __copy__()__deepcopy__() 方法控制拷贝行为
  1. 性能权衡
    • 深拷贝比浅拷贝慢,对复杂结构可能差10倍以上
7. 什么时候用哪种?
  • 用浅拷贝
    • 数据没有嵌套或子对象不可变
    • 需要节省内存/时间
    • 明确希望共享子对象时
  • 用深拷贝
    • 复杂嵌套结构且需要完全独立副本
    • 防止意外修改影响原数据
    • 需要序列化/反序列化时

总结

  • 浅拷贝是"省力但不彻底",深拷贝是"一劳永逸"。
  • 就像备份手机:浅拷贝像云同步(部分依赖原数据),深拷贝像整机克隆(完全独立)。
  • 遇到嵌套结构,当心浅拷贝的"连带影响"!

Python有哪些数据结构?list和set有什么区别?数组与链表的区别?

一、Python内置数据结构

类型

特点

示例

列表(list)

有序、可变、允许重复

[1, 2, 2, 3]

元组(tuple)

有序、不可变、允许重复

(1, "a", True)

集合(set)

无序、可变、不允许重复

{1, 2, 3}

字典(dict)

键值对、键不可重复

{"name": "Alice", "age": 20}

字符串(str)

不可变字符序列

"hello"


二、List(列表) vs Set(集合)

对比项

List

Set

顺序

保持插入顺序

无序(存储顺序不确定)

重复元素

允许重复

自动去重

查找速度

慢(遍历查找,O(n))

极快(哈希表实现,O(1))

适用场景

需要保留顺序或重复数据时

去重、快速成员检测

示例

names = ["Alice", "Bob", "Alice"] # List允许重复 unique_names = {"Alice", "Bob"} # Set自动去重

三、数组(Array) vs 链表(LinkedList)

对比项

数组

链表

内存分配

连续内存,大小固定

非连续内存,动态扩展

访问速度

极快(O(1),直接索引)

慢(O(n),需遍历节点)

插入/删除

慢(需移动元素,O(n))

快(O(1),修改指针即可)

适用场景

频繁随机访问,数据量固定

频繁增删,数据量变化大

通俗比喻

  • 数组:像书架上的书,直接按编号拿(快),但插入新书要挪动其他书(慢)。
  • 链表:像藏宝图,每步告诉你下一个地点在哪,添加新线索只需改箭头(快),但找宝藏要一步步走(慢)。

四、Python中的实现
  1. 数组
    • 使用list(实际是动态数组,非严格数组)
    • array模块(类型受限但更省内存)
import array arr = array.array('i', [1, 2, 3]) # 整型数组
  1. 链表
    • 需手动实现或使用collections.deque(双端队列,近似链表特性)
class Node: def __init__(self, val): self.val = val self.next = None

五、如何选择?
  • 需要快速访问/修改? → 用列表(动态数组)
  • 需要频繁去重/检测存在? → 用集合
  • 需要高效插入/删除? → 考虑链表(但Python中优先用list,除非极端性能需求)

总结:Python的listset分别解决顺序存储和快速查询的问题,而数组与链表的区别是内存结构的根本差异。

python怎么为list去重,list,vector,map区别

✅ Python中如何对list去重

最常见的几种方式如下:

1. 使用set()去重(简单快捷,但会打乱顺序):

my_list = [1, 2, 2, 3, 1] unique_list = list(set(my_list))

2. 保持顺序去重(常用于有序数据)

my_list = [1, 2, 2, 3, 1] unique_list = [] seen = set() for item in my_list: if item not in seen: seen.add(item) unique_list.append(item)

3. 使用dict.fromkeys()(保持顺序,适合Python 3.7+)

my_list = [1, 2, 2, 3, 1] unique_list = list(dict.fromkeys(my_list))

✅ list、vector、map 区别(以编程语言通用概念为基础)

类型

描述

是否有序

是否可重复

常用语言中的名称

list

有序元素集合,支持增删改查

Python list, Java List

vector

动态数组,自动扩容,支持随机访问

C++ vector, Java ArrayList

map

键值对集合,key唯一,用于快速查找

❌(通常无序)

key❌ value✅

Python dict, C++ map, Java HashMap

简单说明:
  • list 适合顺序存储,如游戏关卡列表、操作记录。
  • vector 类似list,但在C++等语言中是支持自动扩容的动态数组,适合频繁插入、访问。
  • map 适合按键快速查找数据,比如通过玩家ID查找昵称或背包。

🎮 举个游戏开发中的例子:

  • 玩家背包中的物品列表:用listvector存储。
  • 用来映射玩家ID到玩家数据:用map(如Python中的dict)。
  • 排行榜查找前100名玩家分数:可以用list去重、排序后显示。

总结:
去重方法要结合“是否保留顺序”来选,三种数据结构各有用途,理解它们的特性可以帮助你在实际开发或测试中选择合适的数据结构。

为什么使用递归?

使用递归的主要原因是为了让代码更简洁、结构更清晰,尤其适合处理具有“自相似”特征的问题,比如树结构、分形结构、回溯搜索、数学归纳等场景。

递归是指一个函数调用自身来解决问题,适用于下面这些情况:

  1. 问题可以分解成规模更小的子问题
  2. 子问题的结构与原问题相同(即自相似)
  3. 最终有一个明确的终止条件(递归出口)

📌 与 for 循环的对比:

对比点

for 循环

递归

代码结构

适合线性问题,步骤明确

适合分治、树形或图形问题

可读性

简单任务更直观

复杂结构更直观(如树的遍历)

性能开销

更高效,无额外栈空间

每次调用会消耗栈空间

可维护性

复杂问题不易扩展

思路清晰,符合数学表达逻辑

错误易发点

循环条件控制

容易造成栈溢出、忘记递归出口


✅ 举个典型例子:树的遍历

假设你在游戏里写一个技能树系统,每个技能点可能有多个子技能。

用递归写:

def traverse(skill_node): print(skill_node.name) for child in skill_node.children: traverse(child)

用 for + 栈写:

stack = [root] while stack: node = stack.pop() print(node.name) stack.extend(node.children)

递归的写法更短,更符合“每个技能点都做同样的事”的逻辑,可读性强,代码更贴近问题本身的结构


✅ 什么时候选择递归?

  • 操作树结构、图结构(如遍历、搜索);
  • 问题天然有递归定义(如斐波那契、阶乘、汉诺塔);
  • 需要进行回溯、分治、深度优先搜索等;
  • 写算法时为了清晰表达思路。

⚠️ 注意:

递归虽然优雅,但也容易出错:

  • 如果没有出口条件,容易栈溢出;
  • 对性能敏感的程序中,可能需要用循环或栈代替递归(叫做尾递归优化或递归转迭代)。

总结:

递归的好处是:代码更简洁、逻辑更自然,特别适合解决自结构问题;但它在性能和稳定性上不如循环,需要谨慎使用。
在实际工作中,如果功能简单、可控,推荐优先用 for;如果是多层结构、递归定义的问题,就大胆用递归。

python2和python3的区别

Python2 和 Python3 的主要区别集中在语法、标准库、字符编码和底层实现等方面。Python3 是 Python 官方推荐使用的版本,Python2 已在 2020 年正式停止支持。

下面从几个核心角度来对比这两个版本:


1. 打印语法的不同

  • Python2:print 是一个语句
print "Hello, world"
  • Python3:print 是一个函数
print("Hello, world")

2. 字符串的处理(编码)

  • Python2 默认字符串是 ASCII 编码str 是字节串,unicode 是独立类型
s = "你好" # 报错,默认 ASCII
  • Python3 默认字符串是 Unicode 编码str 就是 Unicode,bytes 用于字节
s = "你好" # 正常,默认 unicode

3. 整数除法行为

  • Python2:整数除法默认是向下取整(地板除)
print(5 / 2) # 输出 2
  • Python3:整数除法默认是真实除法(保留小数)
print(5 / 2) # 输出 2.5

若要地板除:使用 //


4. xrangerange

  • Python2:
    • range 返回的是列表
    • xrange 返回的是生成器(节省内存)
  • Python3:
    • range 就是生成器,xrange 被取消了

5. input() 的行为

  • Python2:
    • input() 会执行输入的表达式,容易有安全风险
    • raw_input() 才是读取字符串
  • Python3:
    • input() 始终返回字符串,语义更清晰

6. 库兼容性

  • Python3 的标准库进行了重构和改名,例如:
    • urllib → 拆分成 urllib.request, urllib.parse
    • Queuequeue
    • 更统一的异常语法:except Exception as e:

7. 其他特性差异(Python3 的优势)

  • 支持更多高级语法,如:
    • f"" 格式化字符串
    • 类型注解(type hints)
    • async/await 原生支持异步编程
    • 更清晰的迭代器、生成器写法
  • 更好的 Unicode 支持
  • 更一致的语言设计理念(移除了旧的不一致用法)

总结对比表:

功能/特性

Python2

Python3

打印语法

print "abc"

print("abc")

字符编码

默认 ASCII,需手动处理 Unicode

默认 Unicode,字符串更统一

除法行为

5 / 2 = 2

5 / 2 = 2.5

range

/ xrange

range

是列表,xrange

是生成器

range

是生成器,没有 xrange

输入函数

raw_input()

input()

官方支持

已停止支持

持续更新和优化


建议:

如果你正在做任何新项目或测试框架搭建,一定要用 Python3。
Python2 已经是历史版本,虽然一些老项目可能还在维护,但新系统已经不推荐再使用。

Read more

day20|学习前端

{{}}。相当于innerText v-bind:attr绑定属性值。 hooks是一个一个可以调用的函数。composition API 返回对象+解构 const{ sum,add,bigSum}=useSum() 一般组件放到components。路由组件放到pages,views文件夹 to路由:1、字符串写法。2、对象写法(name跳转,path跳转) 集中式状态(数据)管理pinia,redux,vuex 把共享的数据交给集中式管理, pinia落地的东西,就是store v-bind单项绑定。v-model双向绑定   function不缓存,computed计算属性缓存,只有依赖变才重新计算。 computed计算属性函数,根据已有响应式数据计算出新值,具有缓存的功能。 watch 入口文件main.ts App.vue根组件 一般组件导入和使用的方法 插值语法 vue3可以写vue2语法,在vue3里,选项式和组合式是共存的。旧语法可以读出setup东西,

By Ne0inhk
【Linux篇章】穿越网络迷雾:揭开 HTTP 应用层协议的终极奥秘!从请求响应到实战编程,从静态网页到动态交互,一文带你全面吃透并征服 HTTP 协议,打造属于你的 Web 通信利刃!

【Linux篇章】穿越网络迷雾:揭开 HTTP 应用层协议的终极奥秘!从请求响应到实战编程,从静态网页到动态交互,一文带你全面吃透并征服 HTTP 协议,打造属于你的 Web 通信利刃!

本篇摘要 本篇将介绍何为HTTP协议,以及它的请求与答复信息的格式(请求行,请求包头,正文等),对一些比较重要的部分来展开讲解,其他不常用的即一概而过,从静态网页到动态网页的过渡,最后底层基于TCP实现简单的HTTP服务器的代码编写构建一个简单的网页(包含对应的跳转,重定向,动态交互等功能),采取边讲解http结构边用代码形成效果展示的形式进行讲解,望有助! 欢迎拜访:点击进入博主主页 本篇主题:探秘HTTP应用层那些事儿! 制作日期:2025.07.21 隶属专栏:点击进入所属Linux专栏 本文将要介绍的内容的大致流程图如下: 一· 认识HTTP * 在互联网世界中, HTTP(HyperText Transfer Protocol, 超文本传输协议) 是一个至关重要的协议。 它定义了客户端(如浏览器) 与服务器之间如何通信, 以交换或传输超文本(如 HTML 文档) 。 * HTTP 协议是客户端与服务器之间通信的基础。 * 客户端通过 HTTP 协议向服务器发送请求, 服务器收到请求后处理并返回响应。 HTTP 协议是一个无连接、

By Ne0inhk
高校电动车租赁系统信息管理系统源码-SpringBoot后端+Vue前端+MySQL【可直接运行】

高校电动车租赁系统信息管理系统源码-SpringBoot后端+Vue前端+MySQL【可直接运行】

摘要 随着城市化进程的加快和高校规模的不断扩大,校园内的交通问题日益突出。传统的自行车和步行方式已无法满足学生和教职工的出行需求,电动车因其便捷性和环保性逐渐成为校园内主要的交通工具之一。然而,电动车的购买和维护成本较高,许多学生更倾向于选择租赁方式。高校电动车租赁系统的开发旨在解决这一需求,通过信息化手段实现电动车的智能化管理和高效租赁。该系统不仅能够提升校园交通效率,还能减少资源浪费,符合绿色校园的建设理念。关键词:高校交通、电动车租赁、智能化管理、绿色校园、信息化系统。 该系统采用SpringBoot作为后端框架,结合Vue.js前端技术和MySQL数据库,实现了用户管理、电动车信息管理、租赁订单管理等功能模块。SpringBoot提供了高效的开发体验和稳定的运行性能,Vue.js则确保了用户界面的交互性和响应速度,MySQL作为关系型数据库保证了数据的安全性和一致性。系统支持用户注册登录、电动车查询与预订、订单支付与状态跟踪等功能,同时管理员可以通过后台管理界面实现对电动车和用户信息的全面管理。系统的模块化设计和可扩展性为未来的功能升级提供了便利。关键词:SpringBoo

By Ne0inhk
ollama 模型管理、删除模型 、open-webui 开启大模型交互

ollama 模型管理、删除模型 、open-webui 开启大模型交互

文章目录 * ollama 基本信息 * ollama 运行模型 * ollama 模型管理 * 🔧 **方法一:使用命令行删除单个模型** * ⚙️ **方法二:批量删除所有模型** * 🗑️ **方法三:彻底卸载 Ollama(含所有数据)** * ⚠️ **注意事项** * ✅ **验证是否删除成功** * open-webui 安装 开启大模型交互 * open-webui pip 安装 * open-webui 启动服务 * 浏览器访问 http://IP:8082/ : * ❤️ 时不我待,一起学AI ollama 基本信息 * https://ollama.com/ ollama 运行模型 命令行执行即可 0.6B parameter model ollama run qwen3:0.6b 1.7B

By Ne0inhk