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

Python函数缺省参数的 “ 坑 ” (与C++对比学习)

        我们都知道Python函数的缺省参数可以降低我们调用函数的成本,但是一般我们的缺省参数都是不可变对象,如果是可变对象,我们对其多次调用会发生什么呢?

def func(arr=[]):arr.append('Hello')print(arr)func()
func()
func()    

        这貌似很奇怪,因为在学习C++时,打印出来的信息应该都是一致的,如下:

#include <iostream>
#include <vector>
void func(std::vector<int> arr = std::vector<int>())
{arr.push_back(1);for(auto& e : arr){std::cout << e << " ";}std::cout << std::endl;
}
int main()
{func();func();func();return 0;
}

        这是因为在C++中,只有在调用该函数的时候,才会创建对应的缺省参数的对象,所以每次调用都会在栈上创建一个新的vector对象,但是大家一定会观测到每次都地址都是一致的,但是无需担心,因为 arr 的作用域也只是在函数内部,每次调用的时候都是需要重新创建对象的。

void func(std::vector<int> arr = std::vector<int>())
{arr.push_back(1);std::cout << &arr << std::endl;
}

        在Python中,如果你定义了一个函数,并在定义函数参数的时候,为其制定了缺省参数,,那么这个缺省参数就会被维护起来,存储到了函数对象的属性中,直到程序结束或者函数对象被删除。所以我们每次调用的时候,都是在访问同一个缺省参数的对象,因为上面的缺省参数对象是一个可变对象,对其进行append操作就会改变对象的内容,所以就会观测到上面的现象了。

        我们也可以观测一下这个缺省参数对象的地址:

def func(arr=[]):arr.append('Hello')print("id = %d" % (id(arr)))# print(arr)func()
func()
func()

        我们可以观测到对象的id都是一致的,所以也可以证明这几次函数调用的缺省参数对象都是同一个

那如何解决这类问题?

def func(arr=None):if arr is None:arr = []arr.append('Hello')print("id = %d" % (id(arr)))print(arr)func()
func()
func()

        这样设计就没有问题了,因为如果arr是一个空类型None,就会在函数内部重新被赋值成list列表,而此时list列表对象的生命周期和作用域都在函数内,即调用完函数就会被销毁,所以在打印的时候即使id值相同,也是不同对象。

相关文章:

  • MYSQL函数进阶详解:案例解析(第19天)
  • uni-app组件 子组件onLoad、onReady事件无效
  • 如何 提升需求确定性
  • LabVIEW新能源汽车电池性能测试系统
  • 某DingTalk企典 - Token
  • k8s离线安装安装skywalking9.4
  • 眼动追踪技术 | 眼动的分类和模型
  • 【云计算】阿里云、腾讯云、华为云RocketMQ、Kafka、RabbitMq消息队列对比
  • Java 并发集合:CopyOnWrite 写时复制集合介绍
  • 无人机水运应用场景
  • java中如何使用ffmpeg命令来实现视频编码转换
  • python库(2):Passlib库
  • 【Redis】SpringBoot连接Redis
  • Gartner发布软件供应链安全指南:软件供应链攻击造成的损失将从 2023 年的460亿美元上升到2031年的1380亿美元
  • “论单元测试方法及应用”写作框架,软考高级论文,系统架构设计师论文
  • Google 是如何开发 Web 框架的
  • android 一些 utils
  • chrome扩展demo1-小时钟
  • Facebook AccountKit 接入的坑点
  • Java超时控制的实现
  • Linux gpio口使用方法
  • Python 使用 Tornado 框架实现 WebHook 自动部署 Git 项目
  • React+TypeScript入门
  • - 语言经验 - 《c++的高性能内存管理库tcmalloc和jemalloc》
  • 【干货分享】dos命令大全
  • 移动端高清、多屏适配方案
  • 昨天1024程序员节,我故意写了个死循环~
  • #LLM入门|Prompt#1.8_聊天机器人_Chatbot
  • ( )的作用是将计算机中的信息传送给用户,计算机应用基础 吉大15春学期《计算机应用基础》在线作业二及答案...
  • (1)安装hadoop之虚拟机准备(配置IP与主机名)
  • (4)通过调用hadoop的java api实现本地文件上传到hadoop文件系统上
  • (pojstep1.1.1)poj 1298(直叙式模拟)
  • (笔试题)合法字符串
  • (分布式缓存)Redis分片集群
  • (每日持续更新)信息系统项目管理(第四版)(高级项目管理)考试重点整理 第13章 项目资源管理(七)
  • (五) 一起学 Unix 环境高级编程 (APUE) 之 进程环境
  • (一)Mocha源码阅读: 项目结构及命令行启动
  • (译) 函数式 JS #1:简介
  • (转) Face-Resources
  • (转)C#开发微信门户及应用(1)--开始使用微信接口
  • (最全解法)输入一个整数,输出该数二进制表示中1的个数。
  • .NET CORE Aws S3 使用
  • .net core Swagger 过滤部分Api
  • .Net Core/.Net6/.Net8 ,启动配置/Program.cs 配置
  • .NET Framework 4.6.2改进了WPF和安全性
  • .net MVC中使用angularJs刷新页面数据列表
  • .NET 发展历程
  • .NET/C# 检测电脑上安装的 .NET Framework 的版本
  • .NET/C# 推荐一个我设计的缓存类型(适合缓存反射等耗性能的操作,附用法)
  • .netcore 6.0/7.0项目迁移至.netcore 8.0 注意事项
  • .NET关于 跳过SSL中遇到的问题
  • .net中生成excel后调整宽度
  • /dev/VolGroup00/LogVol00:unexpected inconsistency;run fsck manually
  • [2021 蓝帽杯] One Pointer PHP
  • [Android] 修改设备访问权限