python - DataFrame 作为默认函数参数未按预期工作
问题描述
我很困惑为什么 DataFrame 作为默认函数参数不能像我预期的那样工作。这让我感到困惑,为什么我仍然必须在函数调用中指定它。
基本上我已经创建了一个函数来将数据帧合并到一个主数据帧(我将它设置为默认参数),基于一个键(如左连接)
简化的数据框(只是同一个学生,不同的科目分数):
dfA = pd.DataFrame ({'student': ['A'],
'math_score': [50]})
dfB = pd.DataFrame({'student': ['A'],
'eng_score': [70]})
dfC = pd.DataFrame({'student': ['A'],
'sci_score': [80]})
功能(我想通过将它们合并到主df来一一获取他的科目分数)
def merge_selected(df_to_merge, main_df = dfA):
# LEFT JOIN to main_df
main_df = main_df.merge(right=df_to_merge, how='left', on=['student'])
return main_df
使用函数合并两次:
dfA = merge_selected(dfB)
dfA = merge_selected(dfC)
现在这是我不明白的。我eng_score
在第二次合并中输了。不知何故,当我第二次分配dfA
时merge_selected
,它被删除了。
student math_score sci_score
0 A 50 80
但是如果我main_df = dfA
在函数调用中指定:
dfA = merge_selected(dfB, main_df = dfA)
dfA = merge_selected(dfC, main_df = dfA)
我不输eng_score
并得到他所有的分数:
student math_score eng_score sci_score
0 A 50 70 80
基本上我已经解决了这个问题,但希望有人能对此有所了解。
为什么我仍然必须指定main_df
,即使它应该默认为dfA
?
eng_score
另外,如果我不指定,为什么我会输main_df = dfA
?
解决方案
当您使用默认参数 main_df=dfA 定义函数时,该函数会“记住”DataFrame dfA 以供将来所有调用使用。让我们给这个dfA的“原始形式”起一个名字:orig_dfA。
现在,第一次调用merge_selected。您最终使用 orig_dfA 创建了一个新的合并 DataFrame,它存储在内存中的某个位置,与 orig_dfA 不同。
然后,您从函数返回并将 dfA 分配给这个新的合并 DataFrame。事情就是这样。您实际上根本没有更改 orig_dfA 。您只需将名称“dfA”指代这个新的合并 DataFrame,它存储在内存中与 orig_dfA 不同的位置。但是该函数仍然附加到 orig_dfA,它没有改变 - 该函数不知道您希望 main_df 的默认值现在成为“dfA”所指的新 DataFrame!
所以,当涉及到第二个函数调用时,就好像第一个函数从未发生过一样!
这是一个更简单的例子来说明这一点。和以前一样,使用默认值 main_df 定义您的函数。现在,在定义函数之后,立即将 dfA 更改为完全不是 DataFrame 的东西,比如 dfA = 3。现在像第一次一样调用你的函数。你会得到完全相同的输出。
这里发生的事情是两件事的混合:
- 在 Python 中,赋值 (=) 运算符只是将名称绑定到内存中的对象/值。语句 x = 3 不能作为“留出一些将由名称“x”引用的内存,并将值 3 放在那里”,这是人们可能直觉所期望的。相反,它更像是“在内存中的某处创建值 3 并让名称“x”引用它”。
- 当您设置默认参数时,该默认参数引用的对象/值在函数创建时确定并且是固定的。
在您的情况下,在定义转换为“使 main_df 引用 df_A 当前引用的内存中的对象/值”的函数时设置 main_df=df_A 。从这一点开始,您可以让 df_A 引用您喜欢的任何其他内存 - 该函数将始终引用 df_A 在创建函数时引用的同一块内存,而不是 df_A 碰巧引用的任何值函数实际上被调用。
推荐阅读
- java - 带有 springdoc-openapi-ui 的 Swagger UI 不显示生成的“@Controller”类中的 API
- regex - 正则表达式自定义匹配标签ang得到它的组?
- split - 类型错误:字符串索引必须是整数错误,我无法在堆栈溢出时找到解决方案
- asp.net-mvc - 尝试激活 api 控制器时无法解析类型“Microsoft.AspNetCore.SignalR.HubConnectionContext”的服务
- bots - 如何在没有表单的情况下实施 Google Recaptcha v3?
- javascript - 如何在 Vuex 的 createStore() 中使用 Google Maps 函数?
- reactjs - 在子组件中克隆从父组件传递的对象 - React Hooks
- ruby-on-rails - 在连接表 rails 中指定外键
- ios - Snapchat Snap Kit iOS 登录重定向 URL 在 Safari 上不起作用
- python - while 循环不承认 if 语句