0

0

如何通过引用传递变量?

PHPz

PHPz

发布时间:2024-02-09 20:00:05

|

661人浏览过

|

来源于stackoverflow

转载

如何通过引用传递变量?

问题内容

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

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

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

神卷标书
神卷标书

神卷标书,专注于AI智能标书制作、管理与咨询服务,提供高效、专业的招投标解决方案。支持一站式标书生成、模板下载,助力企业轻松投标,提升中标率。

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

虽然这看起来有点麻烦。

相关专题

更多
python开发工具
python开发工具

php中文网为大家提供各种python开发工具,好的开发工具,可帮助开发者攻克编程学习中的基础障碍,理解每一行源代码在程序执行时在计算机中的过程。php中文网还为大家带来python相关课程以及相关文章等内容,供大家免费下载使用。

745

2023.06.15

python打包成可执行文件
python打包成可执行文件

本专题为大家带来python打包成可执行文件相关的文章,大家可以免费的下载体验。

634

2023.07.20

python能做什么
python能做什么

python能做的有:可用于开发基于控制台的应用程序、多媒体部分开发、用于开发基于Web的应用程序、使用python处理数据、系统编程等等。本专题为大家提供python相关的各种文章、以及下载和课程。

757

2023.07.25

format在python中的用法
format在python中的用法

Python中的format是一种字符串格式化方法,用于将变量或值插入到字符串中的占位符位置。通过format方法,我们可以动态地构建字符串,使其包含不同值。php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

617

2023.07.31

python教程
python教程

Python已成为一门网红语言,即使是在非编程开发者当中,也掀起了一股学习的热潮。本专题为大家带来python教程的相关文章,大家可以免费体验学习。

1259

2023.08.03

python环境变量的配置
python环境变量的配置

Python是一种流行的编程语言,被广泛用于软件开发、数据分析和科学计算等领域。在安装Python之后,我们需要配置环境变量,以便在任何位置都能够访问Python的可执行文件。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

547

2023.08.04

python eval
python eval

eval函数是Python中一个非常强大的函数,它可以将字符串作为Python代码进行执行,实现动态编程的效果。然而,由于其潜在的安全风险和性能问题,需要谨慎使用。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

577

2023.08.04

scratch和python区别
scratch和python区别

scratch和python的区别:1、scratch是一种专为初学者设计的图形化编程语言,python是一种文本编程语言;2、scratch使用的是基于积木的编程语法,python采用更加传统的文本编程语法等等。本专题为大家提供scratch和python相关的文章、下载、课程内容,供大家免费下载体验。

705

2023.08.11

c++主流开发框架汇总
c++主流开发框架汇总

本专题整合了c++开发框架推荐,阅读专题下面的文章了解更多详细内容。

25

2026.01.09

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Django 教程
Django 教程

共28课时 | 2.9万人学习

Pandas 教程
Pandas 教程

共15课时 | 0.9万人学习

NumPy 教程
NumPy 教程

共44课时 | 2.8万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号