Arguments are passed by assignment. The rationale behind this is twofold:

  1. the parameter passed in is actually a reference to an object (but the reference is passed by value)
  2. some data types are mutable, but others aren't

So:

  • If you pass a mutable object into a method, the method gets a reference to that same object and you can mutate it to your heart's delight, but if you rebind the reference in the method, the outer scope will know nothing about it, and after you're done, the outer reference will still point at the original object.

  • If you pass an immutable object to a method, you still can't rebind the outer reference, and you can't even mutate the object.

To make it even more clear, let's have some examples.

List - a mutable type

Let's try to modify the list that was passed to a 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)

Output:

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

Since the parameter passed in is a reference to outer_list, not a copy of it, we can use the mutating list methods 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 that was 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)

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

Since the the_list parameter was passed by value, assigning a new list to it had no effect that the code outside the method could see. The the_list was a copy of the outer_list reference, and we had the_list point to a new list, but there was no way to change where outer_list pointed.

String - an immutable type

It's immutable, so there's nothing we can do to change the contents 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)

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

Again, since the the_string parameter was passed by value, assigning a new string to it had no effect that the code outside the method could see. The the_string was a copy of the outer_string reference, and we had the_string point to a new string, but there was no way to change where outer_string pointed.

I hope this clears things up a little.

EDIT: It's been noted that this doesn't answer the question that @David originally asked, "Is there something I can do to pass the variable by actual reference?". Let's work on that.

How do we get around this?

As @Andrea's answer shows, you could return the new value. This doesn't change the way things are passed in, but does let you get the information you want back out:

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)

If you really wanted to avoid using a return value, you could create a class to hold your value and pass it into the function or use an existing class, like 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])

Although this seems a little cumbersome.

Answer from Blair Conrad on Stack Overflow
🌐
Real Python
realpython.com › python-pass-by-reference
Pass by Reference in Python: Background and Best Practices – Real Python
March 18, 2026 - Lists and sets are mutable, as are dictionaries and other mapping types. Strings and tuples are not mutable. Attempting to modify an element of an immutable object will raise a TypeError. Python works differently from languages that support passing arguments by reference or by value.
Discussions

python - How do I pass a variable by reference? - Stack Overflow
Python’s pass-by-assignment scheme isn’t quite the same as C++’s reference parameters option, but it turns out to be very similar to the argument-passing model of the C language (and others) in practice: Immutable arguments are effectively passed “by value.” Objects such as integers and strings ... More on stackoverflow.com
🌐 stackoverflow.com
Don't understand the pass by references vs pass by value in Python
The function code sets and prints a variable. x = 'another value' print (x) Why would this print anything except "another value"? x is changed, and printed... More on reddit.com
🌐 r/learnpython
15
3
May 21, 2021
C++ style pass by reference - Ideas - Discussions on Python.org
I propose specifying a function parameter as being pass-by-reference, using the notation “&name” instead of “name”. The actual argument can be any valid assignment target: a variable, an attribute, a subscript, or even a “&name” in another function. More on discuss.python.org
🌐 discuss.python.org
0
December 18, 2022
How is python pass by reference different from the original "pass by reference" concapt?
This is asked very frequently. The best explanation is here: https://nedbatchelder.com/text/names.html Note that this behaviour is not specific to Python: many modern languages, such as Java, JS, Ruby, and probably more, work the same way. More on reddit.com
🌐 r/learnpython
36
20
February 27, 2022
🌐
Reddit
reddit.com › r/learnpython › how is python pass by reference different from the original "pass by reference" concapt?
r/learnpython on Reddit: How is python pass by reference different from the original "pass by reference" concapt?
February 27, 2022 -

Trying to understand how Python works passing arguments in functions. I've heard that Python's approach is referred to as "pass by assignment" or "pass by object reference".

How does this differ from the more traditional "pass by reference" approach? Hopefully someone can explain it in a way that's easy to understand.

Top answer
1 of 16
3595

Arguments are passed by assignment. The rationale behind this is twofold:

  1. the parameter passed in is actually a reference to an object (but the reference is passed by value)
  2. some data types are mutable, but others aren't

So:

  • If you pass a mutable object into a method, the method gets a reference to that same object and you can mutate it to your heart's delight, but if you rebind the reference in the method, the outer scope will know nothing about it, and after you're done, the outer reference will still point at the original object.

  • If you pass an immutable object to a method, you still can't rebind the outer reference, and you can't even mutate the object.

To make it even more clear, let's have some examples.

List - a mutable type

Let's try to modify the list that was passed to a 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)

Output:

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

Since the parameter passed in is a reference to outer_list, not a copy of it, we can use the mutating list methods 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 that was 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)

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

Since the the_list parameter was passed by value, assigning a new list to it had no effect that the code outside the method could see. The the_list was a copy of the outer_list reference, and we had the_list point to a new list, but there was no way to change where outer_list pointed.

String - an immutable type

It's immutable, so there's nothing we can do to change the contents 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)

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

Again, since the the_string parameter was passed by value, assigning a new string to it had no effect that the code outside the method could see. The the_string was a copy of the outer_string reference, and we had the_string point to a new string, but there was no way to change where outer_string pointed.

I hope this clears things up a little.

EDIT: It's been noted that this doesn't answer the question that @David originally asked, "Is there something I can do to pass the variable by actual reference?". Let's work on that.

How do we get around this?

As @Andrea's answer shows, you could return the new value. This doesn't change the way things are passed in, but does let you get the information you want back out:

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)

If you really wanted to avoid using a return value, you could create a class to hold your value and pass it into the function or use an existing class, like 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])

Although this seems a little cumbersome.

2 of 16
909

The problem comes from a misunderstanding of what variables are in Python. If you're used to most traditional languages, you have a mental model of what happens in the following sequence:

a = 1
a = 2

You believe that a is a memory location that stores the value 1, then is updated to store the value 2. That's not how things work in Python. Rather, a starts as a reference to an object with the value 1, then gets reassigned as a reference to an object with the value 2. Those two objects may continue to coexist even though a doesn't refer to the first one anymore; in fact they may be shared by any number of other references within the program.

When you call a function with a parameter, a new reference is created that refers to the object passed in. This is separate from the reference that was used in the function call, so there's no way to update that reference and make it refer to a new object. In your example:

def __init__(self):
    self.variable = 'Original'
    self.Change(self.variable)

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

self.variable is a reference to the string object 'Original'. When you call Change you create a second reference var to the object. Inside the function you reassign the reference var to a different string object 'Changed', but the reference self.variable is separate and does not change.

The only way around this is to pass a mutable object. Because both references refer to the same object, any changes to the object are reflected in both places.

def __init__(self):         
    self.variable = ['Original']
    self.Change(self.variable)

def Change(self, var):
    var[0] = 'Changed'
🌐
The Python Coding Stack
thepythoncodingstack.com › the python coding stack › if you haven't got a clue what "pass by value" or "pass by reference" mean, read on…
If You Haven't Got A Clue What "Pass By Value" or "Pass By Reference" mean, read on…
August 20, 2024 - Python doesn't use 'pass by reference' or 'pass by value'. Instead, the argument passed to a function is assigned to a new local variable within the function. This local variable is the parameter name.
🌐
Quora
quora.com › Are-strings-passed-by-value-in-Python
Are strings passed by value in Python? - Quora
Answer (1 of 4): A string is immutable in python. Any alteration to the contents of a string results in a new string object. When a string is sent as a parameter into a function, a reference is generated that refers to the actual string value in memory, the reference variable name is an alias to...
🌐
GeeksforGeeks
geeksforgeeks.org › python › pass-by-reference-vs-value-in-python
Pass by reference vs value in Python - GeeksforGeeks
June 3, 2026 - Functions receive references to objects, not separate copies. Mutable objects can be modified inside functions. Immutable objects create new objects when modified, making them behave similarly to pass-by-value. Python passes object references to functions, so mutable objects can be modified inside the function without creating a copy.
Find elsewhere
🌐
Python Guides
pythonguides.com › python-pass-by-reference-or-value
Python Pass By Reference Or Value With Examples
September 6, 2025 - Python doesn’t strictly use call by value or call by reference.
🌐
GeeksforGeeks
geeksforgeeks.org › dsa › how-to-pass-a-string-to-a-function-using-call-by-reference
How to Pass a String to a Function using Call by Reference? - GeeksforGeeks
October 30, 2023 - Passing a string by reference in various programming languages involves using specific mechanisms or constructs to allow the function to modify the original string directly, rather than working with a copy. Here, I'll explain how to achieve this in C++, C#, Python, and JavaScript.
🌐
Tutorial Teacher
tutorialsteacher.com › articles › how-to-pass-value-by-reference-in-python
How to pass value by reference in Python?
Hence, it can be inferred that in Python, a function is always called by passing a variable by reference. It means, if a function modifies data received from the calling environment, the modification should reflect in the original data.
🌐
Python Guides
pythonguides.com › python-pass-by-reference
Python Pass by Reference
February 2, 2026 - When you pass an argument to a function, Python passes a copy of that reference, not a copy of the actual object data. Whether the original data changes depends entirely on whether the object you are passing is mutable (like a list) or immutable ...
🌐
Python
python-list.python.narkive.com › CTxdin4t › newbie-question-about-string-passing-by-ref
Newbie question about string(passing by ref)
Post by lazy I want to pass a string by reference. Don't worry, all function parameters in Python are passed by reference. Actually, just to clarify a little bit if you're understanding "pass by reference" in the sense used in PHP, sort of C, etc.: In Python, you have objects and names.
🌐
Pokutta
pokutta.com › blog › pages › python-pass-by-name.html
Python’s pass-by-name | One trivial observation at a time
January 1, 2019 - What happens in the statement var2 = var2 + "!!" is that on the right-hand side we create a new string object "I am a string!!" and var2 now is assigned to be the name of this new string object. This is because most (if not all) string operations in python result in new objects. As such var1 and var2 are not referring to the same memory block anymore.
🌐
Robert Heaton
robertheaton.com › 2014 › 02 › 09 › pythons-pass-by-object-reference-as-explained-by-philip-k-dick
Is Python pass-by-reference or pass-by-value? | Robert Heaton
The two most widely known and easy to understand approaches to parameter passing amongst programming languages are pass-by-reference and pass-by-value.
🌐
Sololearn
sololearn.com › en › Discuss › 2259297 › python-pass-by-value-and-pass-by-reference
python pass by value and pass by reference | Sololearn: Learn to code for FREE!
Because whoever wrote it, doesn't seem to have a good understanding of Python. In Python, arguments are *always* passed by reference. You can check this by calling the id function on a value outside and inside of the function - it's the same.
🌐
O'Reilly
oreilly.com › library › view › python-programming-on › 1565926218 › ch22s04s03.html
22.4.3. C Strings and Passing by Reference - Python Programming On Win32 [Book]
This class should be initialized with a Python string (which may be empty), and an optional length. Internally, cString maintains a buffer with a null-terminated string and the address of the buffer it passes to the DLL when used as an argument.
🌐
Python.org
discuss.python.org › ideas
C++ style pass by reference - Ideas - Discussions on Python.org
December 18, 2022 - I propose specifying a function parameter as being pass-by-reference, using the notation “&name” instead of “name”. The actual argument can be any valid assignment target: a variable, an attribute, a subscript, or even …
🌐
Intel Community
community.intel.com › t5 › Intel-Fortran-Compiler › Passing-by-reference-a-Python-string-to-Fortran-function › m-p › 1297543
Re: Passing (by reference) a Python string to Fortran function (subroutine) - Intel Community
July 11, 2021 - python allocates memory for b'Hello World' and a pointer pointing to (the beginning of) it this is passed by reference (meaning bu that "no copy is created" In the function upper_fortran, the line ... No. Handwaving a bit on the Python side... Python creates an object in memory for the byte string b'Hello world', references that object in the internals of a c_char_p object and binds a reference to that c_char_p object to the name `in_ptr`. Note that Python requires the byte string object to be immutable.