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

AI 测试全体系详解(自动化测试框架 + 智能缺陷检测 + A/B 测试优化)

AI 测试全体系详解(自动化测试框架 + 智能缺陷检测 + A/B 测试优化)

前言 人工智能技术的深度落地,彻底重构了软件测试的行业生态,传统手工测试、标准化自动化测试的效率瓶颈被打破,AI 与测试领域的融合催生出三大核心应用方向:AI 驱动的自动化测试框架、AI 智能缺陷检测、AI 赋能的 A/B 测试优化。三者相辅相成,前者解决「测试执行效率与覆盖度」问题,中者解决「缺陷精准识别与根因定位」问题,后者解决「产品体验与业务转化的最优决策」问题,共同构建了从功能验证到质量保障、再到业务价值提升的全链路 AI 测试体系。本文将对三大核心方向进行系统化拆解,包含原理剖析、技术选型、完整可运行代码、Mermaid 标准化流程图、工程化 Prompt 示例、可视化图表、落地最佳实践,覆盖理论与实操全维度,所有内容均可直接落地应用。 一、AI 驱动的自动化测试框架:从脚本化到智能化,重构自动化测试核心逻辑 1.1

By Ne0inhk
我发现了一个能“一锅端”豆包、即梦所有AI水印的骚操作,99%的人都不知道!(附保姆级教程)

我发现了一个能“一锅端”豆包、即梦所有AI水印的骚操作,99%的人都不知道!(附保姆级教程)

大家好,我是顾北,专注于 AI 应用探索与副业实践,长期关注 AI 技术趋势、实用工具以及 Github 线索探索。 前天发布的 Google AI Studio 去除水印的小技巧后,就吸引到很多朋友私聊我说:“豆包、即梦以及不同模型 AI 生成的图片能不能去除水印",针对于这个问题,我这两天就吭哧吭哧的找解决方案,你别说,真的就被我找到了。 不管是即梦还是豆包,不管是针对于懂一点 AI 的普通玩家,还是专业的 AI 绘图设计师,看完这篇文章,都有所获的。 接下来,就按照豆包去水印、即梦去水印、以及后面的最终大招来分享给你。请你仔细阅读完,看到后面有惊喜哦! 一键去除豆包生图水印 去除豆包生成图片水印方式有两种。 *  第一种:去除水印操作简单,方便,缺点是有可能去除不干净。 * 第二种:去除水印操作麻烦一点,但优点是一键去除得很干净。

By Ne0inhk
医疗AI时代的生物医学Go编程:高性能计算与精准医疗的案例分析(八)

医疗AI时代的生物医学Go编程:高性能计算与精准医疗的案例分析(八)

5.4 性能测试与结果分析 为了评估GoEHRStream的性能,我们设计测试模拟真实的医院数据流场景,并测量关键指标。 5.4.1 实验环境 * 硬件: * CPU: Intel Xeon E-2288G (8 cores, 16 threads) * RAM: 32 GB DDR4 * Storage: 512 GB NVMe SSD (用于GoEHRStream和BadgerDB) * Network: 1 Gbps Ethernet * 软件: * OS: Ubuntu 20.04 LTS * Go: 1.19 * GoEHRStream: 配置见下文。 * 数据源模拟器: 使用Go编写的程序,模拟多个HIS系统并发发送FHIR Observation事件(生命体征)和HL7

By Ne0inhk
让AI应用开发更简单——蚂蚁集团推出企业级AI集成解决方案

让AI应用开发更简单——蚂蚁集团推出企业级AI集成解决方案

让AI应用开发更简单——蚂蚁集团推出企业级AI集成解决方案 🚀 前言 在AI技术快速迭代的当下,企业级AI应用开发面临着多模型适配难、集成成本高、效果验证周期长等痛点。蚂蚁集团推出的百宝箱开放平台(TBOX Open),正是为解决这些行业痛点而生。作为全链路AI能力集成平台,TBOX Open通过标准化接口和工具链,帮助开发者快速构建智能化的业务系统。 文章目录 * 🚀 前言 * 🌟 核心功能解析 * 1. 全形态开发支持 * 2. 模型盲测系统 * 3. 安全防护体系 * 🎁 开发者福利 * 限时权益(即日起至2025.10.31) * 🛠️ 快速入门指南 * 三步完成集成 🌟 核心功能解析 蚂蚁百宝箱开放平台是一个提供全方位AI能力支持的集成式服务开放平台。通过提供OpenAPI、前后端SDK(Python、Java、Nodejs),以及可一键在Web页嵌入智能体对话界面的WebSDK等服务,助力用户在自己的业务流程中快速集成智能体对话、大模型效果盲测等多种AI应用场景,助力业务拥抱AI。 1. 全形态开

By Ne0inhk