【问题标题】:Python Pass by Reference and dictionary copiesPython 通过引用传递和字典副本
【发布时间】:2018-04-24 10:05:10
【问题描述】:

我正在用 Python 编写一个脚本来模拟辩论者的比赛。但是我遇到了这个奇怪的错误,它看起来像是引用传递问题,但有一些不应该受到引用传递影响的行为。

基本上,团队是一个团队字典,其中每个团队都有一堆字段,包括一个胜利和失败字段,当我第一次构建团队时,它们都被初始化为 0。

然后 df.apda_tournament() 获取一个团队字典,并根据模拟对其进行修改以给出团队的胜负,并返回更新后的团队字典。

由于引用传递的工作原理,传递给 df.apda_tournament() 的团队字典和返回的字典最终都被更改,因为该函数会更改传递字典中记录的胜负并返回它。因此:

apda_results == apda_teams

如我所料返回 True。

奇怪的是 df.apda_tournament() 还改变了 apda_teams 是其副本的原始团队字典。所以它最终是这样的:

apda_teams == teams

同样返回真。这很奇怪,因为当我声明它时似乎 apda_teams 只是对团队的引用而不是副本,因为我在函数之外声明了它,所以我不会期望它。

有人可以准确解释这里发生了什么吗?另外我怎样才能避免这种情况,这样 apda_teams 实际上是团队字典的唯一副本,而不仅仅是对内存中记录的引用?

下面附上代码:

import debate_functions as df

dbtr_num = 64
team_num = dbtr_num / 2
dbtr_mn_mn = 200
dbtr_mn_std = 80
dbtr_std_mn = 80
dbtr_std_std = 60
judge_bias = 70

dbtrs = df.make_debaters(dbtr_num, dbtr_mn_mn, dbtr_mn_std, dbtr_std_mn, dbtr_std_std)
teams = df.make_teams(dbtrs, dbtr_mn_mn, dbtr_mn_std)
print(teams)
apda_teams = teams
para_teams = teams

apda_results = df.apda_tournament(5, apda_teams, judge_bias)
print('Check this')
print(apda_results == apda_teams)
print(apda_teams == teams)

运行返回:

Check this
True
True

【问题讨论】:

  • Python 不像 C 那样工作,其传递引用或值的概念。长话短说:如果您不明确复制字典,它将在调用和分配时保持相同的对象。
  • 是的,我明白了,我特别想知道这段代码中的团队,因为我明确地将它复制到 apda_teams,然后只调用 apda_teams 上的函数,但团队正在被修改。

标签: python dictionary pass-by-reference


【解决方案1】:

在python列表中,字典是可变的(我们可以修改内容)。因此,每当您将列表、字典传递给任何函数或分配给任何变量时,它都会指向给定变量的引用。

字符串、数字、元组是不可变的(我们不能修改内容)。因此,每当您将元组字符串、数字分配给任何函数或分配给任何变量时,它都会复制该值。

【讨论】:

  • 是的,我明白这一点,这就是 (apda_results == apda_teams) 评估为 True 的原因。我想知道的是为什么 (apda_teams == teams) 也评估为真,当 apda_teams 是团队的副本时,当它传递给函数时会被更改。现在,团队也被传递给函数的 apda_teams 所改变,即使团队从未通过任何函数传递。
  • 抱歉耽搁了,apda_teams = 团队(分配与参考相同),您需要像 apda_teams = dict(teams) 或 list apda_teams = list(teams) 那样执行 deepcopy
猜你喜欢
  • 2020-07-11
  • 1970-01-01
  • 2012-03-21
  • 1970-01-01
  • 2017-07-29
  • 2011-04-03
  • 1970-01-01
  • 2021-10-13
相关资源
最近更新 更多