文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

如何通过引用传递变量?

2024-02-09 20:12

关注

问题内容

我编写这个类是为了测试:

class PassByReference:
    def __init__(self):
        self.variable = 'Original'
        self.change(self.variable)
        print(self.variable)

    def change(self, var):
        var = 'Changed'

当我尝试创建实例时,输出是 original。所以python中的参数似乎是按值传递的。那是对的吗?如何修改代码才能达到引用传递的效果,使得输出为changed

有时人们会感到惊讶,像 x = 1 这样的代码(其中 x 是参数名称)不会影响调用者的参数,但像 x[0] = 1 这样的代码却会影响调用者的参数。发生这种情况是因为尽管有 = 语法,但项目分配切片分配变异现有对象的方法,而不是重新分配变量。请参阅为什么函数可以修改调用者感知到的某些参数,但不能修改其他参数?了解详情。

另请参阅按引用传递与按值传递之间有什么区别?用于重要的、与语言无关的术语讨论。


正确答案


参数是通过赋值传递。这背后的理由有两个:

  1. 传入的参数实际上是对象的引用(但引用是按值传递的)
  2. 某些数据类型是可变的,但其他数据类型则不然

所以:

  • 如果将一个可变对象传递给方法,该方法将获得对同一对象的引用,并且您可以随心所欲地改变它,但是如果您在方法时,外部作用域对此一无所知,完成后,外部引用仍将指向原始对象。

  • 如果将不可变对象传递给方法,您仍然无法重新绑定外部引用,甚至无法更改该对象。

为了更清楚地说明这一点,让我们举一些例子。

列表 - 可变类型

让我们尝试修改传递给方法的列表:

def try_to_change_list_contents(the_list):
    print('got', the_list)
    the_list.append('four')
    print('changed to', the_list)

outer_list = ['one', 'two', 'three']

print('before, outer_list =', outer_list)
try_to_change_list_contents(outer_list)
print('after, outer_list =', outer_list)

输出:

before, outer_list = ['one', 'two', 'three']
got ['one', 'two', 'three']
changed to ['one', 'two', 'three', 'four']
after, outer_list = ['one', 'two', 'three', 'four']

由于传入的参数是对 outer_list 的引用,而不是它的副本,因此我们可以使用变异列表方法来更改它,并将更改反映在外部范围中。

现在让我们看看当我们尝试更改作为参数传入的引用时会发生什么:

def try_to_change_list_reference(the_list):
    print('got', the_list)
    the_list = ['and', 'we', 'can', 'not', 'lie']
    print('set to', the_list)

outer_list = ['we', 'like', 'proper', 'english']

print('before, outer_list =', outer_list)
try_to_change_list_reference(outer_list)
print('after, outer_list =', outer_list)

输出:

before, outer_list = ['we', 'like', 'proper', 'english']
got ['we', 'like', 'proper', 'english']
set to ['and', 'we', 'can', 'not', 'lie']
after, outer_list = ['we', 'like', 'proper', 'english']

由于 the_list 参数是按值传递的,因此为其分配新列表不会对方法外部的代码产生任何影响。 the_listouter_list 引用的副本,我们让 the_list 指向一个新列表,但无法更改 outer_list 指向的位置。

字符串 - 不可变类型

它是不可变的,因此我们无法更改字符串的内容

现在,让我们尝试更改引用

def try_to_change_string_reference(the_string):
    print('got', the_string)
    the_string = 'in a kingdom by the sea'
    print('set to', the_string)

outer_string = 'it was many and many a year ago'

print('before, outer_string =', outer_string)
try_to_change_string_reference(outer_string)
print('after, outer_string =', outer_string)

输出:

before, outer_string = it was many and many a year ago
got it was many and many a year ago
set to in a kingdom by the sea
after, outer_string = it was many and many a year ago

同样,由于 the_string 参数是按值传递的,因此为其分配新字符串不会对方法外部的代码看到任何影响。 the_stringouter_string 引用的副本,我们让 the_string 指向一个新字符串,但无法更改 outer_string 指向的位置。

我希望这能让事情变得更清楚。

编辑:有人指出,这并没有回答 @david 最初提出的问题:“我可以做些什么来通过实际引用传递变量吗?”。让我们努力吧。

我们如何解决这个问题?

正如@andrea的回答所示,您可以返回新值。这不会改变传入内容的方式,但可以让您获取想要的信息:

def return_a_whole_new_string(the_string):
    new_string = something_to_do_with_the_old_string(the_string)
    return new_string

# then you could call it like
my_string = return_a_whole_new_string(my_string)

如果您确实想避免使用返回值,您可以创建一个类来保存您的值并将其传递给函数或使用现有的类,例如列表:

def use_a_wrapper_to_simulate_pass_by_reference(stuff_to_change):
    new_string = something_to_do_with_the_old_string(stuff_to_change[0])
    stuff_to_change[0] = new_string

# then you could call it like
wrapper = [my_string]
use_a_wrapper_to_simulate_pass_by_reference(wrapper)

do_something_with(wrapper[0])

虽然这看起来有点麻烦。

以上就是如何通过引用传递变量?的详细内容,更多请关注编程网其它相关文章!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 资料下载
  • 历年真题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯