Python中如何按引用传递变量 技术背景 在Python里,参数传递的方式常常会让开发者感到困惑,尤其是与传统的按值传递或按引用传递概念对比时。Python采用的是按赋值传递的方式,这与参数是可变对象还是不可变对象密切相关。理解Python的变量传递机制,对于编写正确且高效的代码十分关键。
实现步骤 1. 理解可变和不可变对象 可变对象 :像列表、字典这类对象是可变的,在函数内部可以修改其内容。不可变对象 :如字符串、整数等对象是不可变的,在函数内部无法修改其内容。2. 传递可变对象 若传递的是可变对象,函数能直接修改该对象的内容。示例如下:
1 2 3 4 5 6 7 8 9 10 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)
输出结果:
1 2 3 4 before, outer_list = ['one', 'two', 'three'] got ['one', 'two', 'three'] changed to ['one', 'two', 'three', 'four'] after, outer_list = ['one', 'two', 'three', 'four']
3. 传递不可变对象 当传递不可变对象时,函数内部无法修改该对象。示例如下:
1 2 3 4 5 6 7 8 9 10 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)
输出结果:
1 2 3 4 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
4. 模拟按引用传递 若要模拟按引用传递不可变对象,可采用以下方法:
1 2 3 4 5 6 7 def return_a_whole_new_string (the_string ): new_string = the_string.upper() return new_string my_string = 'hello' my_string = return_a_whole_new_string(my_string)print (my_string)
1 2 3 4 5 6 7 def use_a_wrapper_to_simulate_pass_by_reference (stuff_to_change ): new_string = stuff_to_change[0 ].upper() stuff_to_change[0 ] = new_string wrapper = ['hello' ] use_a_wrapper_to_simulate_pass_by_reference(wrapper)print (wrapper[0 ])
核心代码 传递可变对象 1 2 3 4 5 6 7 def try_to_change_list_contents (the_list ): the_list.append('new_item' ) return the_list outer_list = [1 , 2 , 3 ] new_list = try_to_change_list_contents(outer_list)print (new_list)
传递不可变对象并模拟按引用传递 1 2 3 4 5 6 7 def modify_wrapper (wrapper ): wrapper[0 ] = wrapper[0 ] * 2 return wrapper wrapper = [5 ] modify_wrapper(wrapper)print (wrapper[0 ])
最佳实践 当需要修改传入的对象时,使用可变对象(如列表、字典)。 若要模拟按引用传递不可变对象,可使用返回值或包装类。 在类的实例方法中,通过self
访问和修改实例属性。 常见问题 1. 为什么在函数内部重新赋值参数,外部变量不受影响? 因为参数是按赋值传递的,函数内部的参数只是外部变量的一个引用副本。重新赋值参数只是让该副本指向了新的对象,而外部变量的引用并未改变。
2. 如何判断一个对象是可变还是不可变的? 可查看对象的文档或尝试修改对象。若修改操作会创建新对象,那么该对象是不可变的;若修改操作能直接改变对象的内容,那么该对象是可变的。