How to pass variable by reference?

PHPz
Release: 2024-02-09 20:00:05
forward
596 people have browsed it

How to pass variable by reference?

Question content

I wrote this class for testing:

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

    def change(self, var):
        var = 'Changed'
Copy after login

When I try to create an instance, the output is original. So parameters in python seem to be passed by value. Is that right? How to modify the code to achieve the effect of reference passing so that the output is changed?

Sometimes people are surprised that code like x = 1 (where x is the parameter name) does not affect the caller's parameters, but code like Code like x[0] = 1 will affect the caller's parameters. This happens because despite the = syntax, item assignment and slice assignment are methods of mutating existing objects, while Not reassigning variables. See Why can a function modify some parameters as perceived by the caller, but not others? Learn more.

See also What is the difference between pass by reference and pass by value? For important, language-independent terminology discussions.


Correct answer


The parameters are passed by assignment. There are two reasons behind this:

  1. The parameter passed in is actually a reference to the object (but the reference is passed by value)
  2. Some data types are mutable, but others are not

so:

  • If you pass a mutable object to a method, the method will get a reference to the same object and you can change it however you want, but if you are in the outer scope of the method Knowing nothing about it, when you're done, the external reference will still be pointing to the original object.

  • If you pass an immutable object to a method, you still cannot rebind the external reference or even change the object.

To illustrate this more clearly, let's give some examples.

List - mutable type

Let’s try modifying the list passed to the method:

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)
Copy after login

Output:

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

Since the parameter passed in is a reference to outer_list and not a copy of it, we can use the mutate list method to change it and have the changes reflected in the outer scope.

Now let's see what happens when we try to change the reference passed in as a parameter:

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)
Copy after login

Output:

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']
Copy after login

Since the_list parameter is passed by value, assigning it a new list will not have any impact on code outside the method. the_list is a copy of the outer_list reference, we have the_list pointing to a new list, but there is no way to change where outer_list points to.

String - immutable type

It is immutable, so we cannot change the content of the string

Now, let’s try to change the reference

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)
Copy after login

Output:

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
Copy after login

Likewise, since the_string parameter is passed by value, assigning it a new string will not have any visible effect on code outside the method. the_string is a copy of the outer_string reference, we have the_string pointing to a new string, but there is no way to change the location outer_string points to.

I hope this makes things clearer.

Edit: Someone pointed out that this doesn't answer the original question posed by @david: "Is there anything I can do to pass the variable by actual reference?". Let's work hard.

How do we solve this problem?

As @andrea's answer shows, you can return new values. This doesn't change how the content is passed in, but it allows you to get the information you want:

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)
Copy after login

If you really want to avoid using the return value, you can create a class to hold your value and pass it to the function or use an existing class, such as a list:

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])
Copy after login

Although this seems a bit troublesome.

The above is the detailed content of How to pass variable by reference?. For more information, please follow other related articles on the PHP Chinese website!

Related labels:
source:stackoverflow.com
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template