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

默认参数 d = {} 的陷阱

默认参数 d = {} 的陷阱

  • 问题需求
  • 思路
  • 代码实现
  • 默认参数d = {}的陷阱
  • 解决办法
    • 1、在函数外为每个字符串创建空字典统计词频
    • 2、函数改为每次调用时创建新字典,避免数据污染
  • 举一反三

问题需求

统计两个字符串的中文词语出现次数

思路

先使用jieba库分词功能处理字符串,再用字典统计词频

代码实现

# 导包、设置变量
import jieba as j
str1 = "默认参数"*20
str2 = "默认变量"*10
print(str1)
print(str2)

输出

默认参数默认参数默认参数默认参数默认参数默认参数默认参数默认参数默认参数默认参数默认参数默认参数默认参数默认参数默认参数默认参数默认参数默认参数默认参数默认参数
默认变量默认变量默认变量默认变量默认变量默认变量默认变量默认变量默认变量默认变量
# 定义统计词频的函数
def get_amount(str_,d = {}):
    for word in j.lcut(str_):
        d[word] = d.get(word,0) + 1
    return d
# 调用函数统计两个字符串词频
words_num1 = get_amount(str1)
words_num2 = get_amount(str2)
print(words_num1)
print(words_num2)

输出

Building prefix dict from the default dictionary ...
Dumping model to file cache C:\Users\walfar\AppData\Local\Temp\jieba.cache
Loading model cost 0.624 seconds.
Prefix dict has been built successfully.
{'默认': 30, '参数': 20, '变量': 10}
{'默认': 30, '参数': 20, '变量': 10}

最后统计结果是对两个字符串所有词语的词频统计

默认参数d = {}的陷阱

Python 函数中的默认参数会在函数定义时初始化一次,而非每次调用时重新创建。当连续调用 get_amount(str1)和get_amount(str2)时,第二次调用会 复用第一次调用后的字典,两次的返回值都是d,words_num1 和 words_num2指向的都是字典d的地址?

做个实验:

def test(d = {}):
        d["666"] = d.get("666",0) + 1
        return d
a = test()
print("第一次调用,变量a存储内容",a)
b = test()
print("第二次调用,变量a存储内容",a)
print("第二次调用,变量b存储内容",b)
c = test()
print("第三次调用,变量a存储内容",a)
print("第三次调用,变量b存储内容",b)
print("第三次调用,变量c存储内容",c)
print("a b c 三个变量的地址:","\n",id(a),"\n",id(b),"\n",id(c))

输出

第一次调用,变量a存储内容 {'666': 1}
第二次调用,变量a存储内容 {'666': 2}
第二次调用,变量b存储内容 {'666': 2}
第三次调用,变量a存储内容 {'666': 3}
第三次调用,变量b存储内容 {'666': 3}
第三次调用,变量c存储内容 {'666': 3}
a b c 三个变量的地址: 
 2099268147584 
 2099268147584 
 2099268147584

解决办法

1、在函数外为每个字符串创建空字典统计词频

# 导包、设置变量
import jieba as j
str1 = "默认参数"*20
str2 = "默认变量"*10
print(str1)
print(str2)
words_num1 = {}
words_num2 = {}
# 定义统计词频的函数
def get_amount(str_,d):
    for word in j.lcut(str_):
        d[word] = d.get(word,0) + 1
get_amount(str1,words_num1)
get_amount(str2,words_num2)
print(words_num1)
print(words_num2)

输出

默认参数默认参数默认参数默认参数默认参数默认参数默认参数默认参数默认参数默认参数默认参数默认参数默认参数默认参数默认参数默认参数默认参数默认参数默认参数默认参数
默认变量默认变量默认变量默认变量默认变量默认变量默认变量默认变量默认变量默认变量
{'默认': 20, '参数': 20}
{'默认': 10, '变量': 10}

统计结果符合预期

2、函数改为每次调用时创建新字典,避免数据污染

# 导包、设置变量
import jieba as j
str1 = "默认参数"*20
str2 = "默认变量"*10
print(str1)
print(str2)
# 定义统计词频的函数
def get_amount(str_,d=None):
    if d is None:
        d = {}
    for word in j.lcut(str_):
        d[word] = d.get(word,0) + 1
    return d
words_num1 = get_amount(str1)
words_num2 = get_amount(str2)
print(words_num1)
print(words_num2)

输出

默认参数默认参数默认参数默认参数默认参数默认参数默认参数默认参数默认参数默认参数默认参数默认参数默认参数默认参数默认参数默认参数默认参数默认参数默认参数默认参数
默认变量默认变量默认变量默认变量默认变量默认变量默认变量默认变量默认变量默认变量
{'默认': 20, '参数': 20}
{'默认': 10, '变量': 10}

结果同样符合预期

举一反三

默认参数 d = {} 有陷阱,那么默认参数为空字符串、空列表 string = “” list = [],是否同样存在陷阱?

# 任务要求 两两拼接字符串
str1 = "你干嘛"
str2 = "哎呦"
str3 = "诞生于1996"
str4 = "梦想做说唱领袖"

# 定义拼接字符串函数
def put_together(s1,s2,s=""):
    s = s + s1+s2
    return s
caixukun = put_together(str1,str2)
print(caixukun)
wangziyi = put_together(str3,str4)
print(wangziyi)

输出

你干嘛哎呦
诞生于1996梦想做说唱领袖

打印id

print(id(caixukun))
print(id(wangziyi))
2099268620528
2099362636720

不存在数据污染问题
默认参数 s=“” 的不存在陷阱?还是我的实验设置有问题?

下面测试默认参数为空列表的情况

# 任务要求 两两将字符串放入两个列表中
str1 = "你干嘛"
str2 = "哎呦"
str3 = "诞生于1996"
str4 = "梦想做说唱领袖"

# 定义拼接字符串函数
def put_in_list(s1,s2,ls = []):
    ls.append(s1)
    ls.append(s2)
    return ls
caixukun = put_in_list(str1,str2)
print(caixukun,id(caixukun))
wangziyi = put_in_list(str3,str4)
print(wangziyi,id(wangziyi))

输出

['你干嘛', '哎呦'] 2099362695808
['你干嘛', '哎呦', '诞生于1996', '梦想做说唱领袖'] 2099362695808

默认参数为空列表的情况存在陷阱


http://www.kler.cn/a/591065.html

相关文章:

  • springboot项目日志不打印
  • Using SAP S4hana An Introduction for Business Users
  • Linux上的`i2c-tools`工具集的详细介绍;并利用它操作IMX6ULL的I2C控制器进而控制芯片AP3216C读取光照值和距离值
  • 【算法题解答·七】哈希
  • VulnHub-Billu_b0x通关攻略
  • EditRocket for Mac v5.0.2 文本编辑器 支持M、Intel芯片
  • 基于多头注意机制的多尺度特征融合的GCN的序列数据(功率预测、故障诊断)模型及代码详解
  • 在WINDOWS中如何运行VBS脚本,多种运行方式
  • vscode vue3 jsconfig 与 tsconfig的区别
  • 扩展01:企业级Nginx+Keepalived双主架构实战
  • Hyperlane:Rust 语言打造的 Web 后端框架新标杆
  • LLM中lora的梯度更新策略公式解析
  • WiFi IEEE 802.11协议精读:IEEE 802.11-2007,19,ERP specification,802.11g,整合15/17/18
  • reactive数据修改无效
  • Visual Studio2022 中的键盘注释快捷方式
  • R语言绘图 | 环状柱状图+散点柱状组合图绘制
  • Spring中的循环依赖问题是什么?
  • 五种方案实现双链路可靠数据传输
  • 顺序表的C语言实现与解析
  • MySQL事务介绍