gpt4 book ai didi

python - 如何通过引用传递变量?

转载 作者:太空宇宙 更新时间:2023-11-03 12:08:02 24 4
gpt4 key购买 nike

参数是按引用传递还是按值传递?如何通过引用传递以便下面的代码输出 'Changed' 而不是 'Original'

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

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

另请参阅:Why can a function modify some arguments as perceived by the caller, but not others?

最佳答案

参数是 passed by assignment .这背后的理由是双重的:

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

所以:

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

  • 如果您将一个不可变对象传递给一个方法,您仍然不能重新绑定(bind)外部引用,甚至不能改变该对象。

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

List - 可变类型

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

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的引用,而不是它的副本,我们可以使用变异列表方法来更改它并将更改反射(reflect)在外部范围中。

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

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尖头。

String - 不可变类型

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

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

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])

虽然这看起来有点麻烦。

关于python - 如何通过引用传递变量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20638817/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com