当前位置: 首页 > news >正文

【小白笔记】功能函数与主函数的布局

1. 功能函数写在主函数内部(嵌套函数)是否OK?

完全可以!这是Python中非常常见且规范的写法,尤其适合「功能函数仅为主函数服务、不对外暴露」的场景(比如这里的partitionquickselect只给findKthLargest用)。

def findKthLargest(nums, k):# 补充:参数校验(鲁棒性)ifnot nums: raise ValueError("数组不能为空")n=len(nums)ifk<1or k>n: raise ValueError(f"k值必须在1到{n}之间")k_target=n - k# 第k大 → 第n-k小# 分区函数:单边循环法(选右边界为pivot)def partition(left, right): pivot=nums[right]# 基准值(右边界)i=left# 小于pivot区域的右边界# 遍历[left, right-1],把小于pivot的元素放到左边forjinrange(left, right):ifnums[j]<pivot: nums[i], nums[j]=nums[j], nums[i]i+=1# 把pivot放到最终位置(i的位置)nums[i], nums[right]=nums[right], nums[i]returni# 返回pivot的索引# 递归版快速选择def quickselect(left, right):# 递归终止条件:区间只剩一个元素ifleft==right:returnnums[left]# 分区,得到pivot的索引(修复:变量名改为pivot_idx,避免冲突)pivot_idx=partition(left, right)# 根据pivot_idx和k_target的关系缩小范围ifk_target<pivot_idx:# 目标在左区,递归左区间returnquickselect(left, pivot_idx -1)elifk_target>pivot_idx:# 目标在右区,递归右区间returnquickselect(pivot_idx +1, right)else:# 找到目标,直接返回returnnums[pivot_idx]# 调用递归,初始区间[0, n-1]returnquickselect(0, n -1)# 测试用例:预期输出5(数组[3,2,1,5,6,4]的第2大元素是5)print(findKthLargest([3,2,1,5,6,4],2))# 输出:5
2. 能否把主函数写完,后面再写功能函数?

也可以!只要在调用功能函数之前,函数已经被定义即可(Python是「顺序执行+函数定义提升」,但调用必须在定义之后)。

3. 为什么原代码要把功能函数嵌套在主函数内部?

原布局的核心目的是:

  • 封装性partitionquickselectfindKthLargest的「内部辅助函数」,不需要被外部调用,嵌套后能避免污染全局命名空间;
  • 变量共享:嵌套函数可以直接访问主函数的变量(比如k_targetnums),无需额外传参,代码更简洁;
  • 逻辑内聚:相关功能集中在主函数内部,代码可读性更高(不用跳来跳去)。

布局1:保持嵌套(原布局,推荐)

这是最推荐的写法,符合「高内聚、低耦合」的设计原则,也是你原代码的布局,优点如上述所说。

布局2:功能函数移到主函数外部(你想要的“主函数写完再写功能函数”)

如果想把partitionquickselect移到外部,需要额外传递numsk_target(因为无法直接共享主函数变量),代码如下:

# 主函数(先写)deffindKthLargest(nums,k):# 参数校验ifnotnums:raiseValueError("数组不能为空")n=len(nums)ifk<1ork>n:raiseValueError(f"k值必须在1到{n}之间")k_target=n-k# 第k大 → 第n-k小# 调用外部的快速选择函数returnquickselect(nums,k_target,0,n-1)# 功能函数1:分区(后写)defpartition(nums,left,right):pivot=nums[right]# 基准值(右边界)i=left# 小于pivot区域的右边界forjinrange(left,right):ifnums[j]<pivot:nums[i],nums[j]=nums[j],nums[i]i+=1nums[i],nums[right]=nums[right],nums[i]returni# 返回pivot的索引# 功能函数2:递归版快速选择(后写)defquickselect(nums,k_target,left,right):# 递归终止条件:区间只剩一个元素ifleft==right:returnnums[left]# 分区,得到pivot的索引pivot_idx=partition(nums,left,right)# 根据pivot_idx和k_target的关系缩小范围ifk_target<pivot_idx:returnquickselect(nums,k_target,left,pivot_idx-1)elifk_target>pivot_idx:returnquickselect(nums,k_target,pivot_idx+1,right)else:returnnums[pivot_idx]# 测试用例print(findKthLargest([3,2,1,5,6,4],2))# 输出:5

布局3:折中方案(主函数在前,嵌套函数在后)

如果你只是觉得嵌套函数放在主函数中间“打断了主函数逻辑”,可以把嵌套函数移到主函数末尾(仍保持嵌套),逻辑更连贯:

deffindKthLargest(nums,k):# 第一步:参数校验(主逻辑1)ifnotnums:raiseValueError("数组不能为空")n=len(nums)ifk<1ork>n:raiseValueError(f"k值必须在1到{n}之间")# 第二步:转换k值(主逻辑2)k_target=n-k# 第三步:调用内部函数(主逻辑3)returnquickselect(0,n-1)# ------------ 嵌套函数移到主函数末尾 ------------# 功能函数1:分区defpartition(left,right):pivot=nums[right]i=leftforjinrange(left,right):ifnums[j]<pivot:nums[i],nums[j]=nums[j],nums[i]i+=1nums[i],nums[right]=nums[right],nums[i]returni# 功能函数2:快速选择defquickselect(left,right):ifleft==right:returnnums[left]pivot_idx=partition(left,right)ifk_target<pivot_idx:returnquickselect(left,pivot_idx-1)elifk_target>pivot_idx:returnquickselect(pivot_idx+1,right)else:returnnums[pivot_idx]# 测试用例print(findKthLargest([3,2,1,5,6,4],2))# 输出:5

不同布局的优缺点对比

布局方式优点缺点
嵌套函数(原布局)1. 封装性好;2. 共享变量,少传参;3. 逻辑内聚主函数中间被嵌套函数打断,视觉上不连贯
外部函数(布局2)1. 主函数逻辑完整;2. 函数可复用1. 多传参(nums/k_target);2. 污染全局命名空间
嵌套函数放末尾(布局3)1. 保留封装性;2. 主逻辑连贯Python中函数内的代码顺序执行,嵌套函数定义必须在调用前(布局3中return quickselectquickselect定义前,会报错!)

⚠️ 注意:布局3有致命问题——Python执行函数时是「从上到下顺序执行」,return quickselect(0, n-1)会先执行,但此时quickselect还没定义,会抛出NameError!因此布局3不可用,这也是原代码把嵌套函数放在调用前的原因。


总结

  1. 功能函数写在主函数内部(嵌套)是完全OK的,且是推荐写法(封装性+内聚性更好);
  2. 可以把功能函数移到主函数外部(主函数写完再写),但需要额外传递参数,牺牲了部分简洁性;
  3. 原代码的嵌套布局核心优势是共享变量、封装辅助函数,这也是快速选择/排序这类算法的常规写法;
  4. 若追求主函数逻辑连贯,优先选「外部函数布局(布局2)」,而非「嵌套函数放末尾(布局3)」(会报错)。

如果你的核心诉求是“主函数代码不被嵌套函数打断”,布局2是最优选择;如果更看重代码简洁和封装性,原嵌套布局更合适。

http://www.jsqmd.com/news/440536/

相关文章:

  • 短视频运营资源合集
  • C++游戏开发之旅 24
  • 2026年知名的单轨吊马达公司推荐:气动单轨吊车/单轨吊气动葫芦实力工厂推荐 - 行业平台推荐
  • 体态矫正资源合集
  • 【2026年最新600套毕设项目分享】基于SpringBoot+Vue的知识产权管理系统(14060)
  • 【小白笔记】迭代与递归的区别
  • Mac双开微信终极指南:一台电脑轻松登录两个微信账号 - 指南
  • 在Revit中创建并导入文字渲染模型的步骤详解
  • 北京DeepSeek推广公司有哪些?2026年GEO服务商能力与定位解析 - 品牌2026
  • 计数公式总结
  • 2026年热门的废水处理工程品牌推荐:生活废水处理/VOCs有机废水处理实力厂家如何选 - 行业平台推荐
  • 2026年质量好的工业除湿机工厂推荐:转轮除湿机/除湿机品牌/家用除湿机稳定供应商推荐 - 行业平台推荐
  • 云主机ubuntu24上安装openclaw操作步骤详解,避坑指南
  • 北京豆包广告服务商有哪些?2026年主流GEO机构能力梳理 - 品牌2026
  • 北京DeepSeek服务商有哪些?2026年主流GEO机构能力梳理 - 品牌2026
  • 腾讯云主机上超级简单的安装openclaw方法
  • 2026年口碑好的蒸汽消音器公司推荐:吹管消音器/蒸汽加热消音器厂家推荐哪家好 - 行业平台推荐
  • 2026年知名的铝业用硝酸钠厂家推荐:陶瓷用硝酸钠厂家推荐参考 - 品牌宣传支持者
  • C#/.NET/.NET Core优秀项目和框架2026年2月简报
  • DeepSeek推广怎么做?2026年主流GEO服务商能力与适配分析 - 品牌2026
  • 2026年评价高的智能液压机工厂推荐:四柱液压机/力位移液压机销售厂家哪家好 - 品牌宣传支持者
  • AI获客如何破局?2026年GEO服务商全景解析与选型指南 - 品牌2026
  • 2026年热门的高压无功补偿柜公司推荐:高压无功补偿装置/高压SVG动态无功补偿装置可靠供应商推荐 - 品牌宣传支持者
  • 2026年口碑好的衣柜灯品牌推荐:全屋定制衣柜灯可靠供应商推荐 - 品牌宣传支持者
  • 2026年质量好的不锈钢合页品牌推荐:子母不锈钢合页/钢质门不锈钢合页厂家推荐哪家好 - 品牌宣传支持者
  • YOLOv11涨点改进| CVPR 2026 |全网独家首发、特征融合改进篇 | 引入 LFSB 差分双维注意融合模块,通过交替特征融合与分离策略,能够精准区分目标特征,顶会助力YOLOv11有效涨点
  • TRAE CN + 方舟 Coding Plan搭建
  • PyTorch的slice究竟做了什麼事?-- stride和stride_offset的妙用
  • 2026年知名的面粉机品牌推荐:荞麦面粉机/石磨面粉机/玉米糁面粉机销售厂家哪家好 - 品牌宣传支持者
  • 2026年比较好的触摸一体机厂家推荐:酒店触摸一体机用户口碑认可厂家 - 品牌宣传支持者