tl;dr: You're right that Python's semantics are essentially Java's semantics, without any primitive types.


"Passed by assignment" is actually making a different distinction than the one you're asking about.1 The idea is that argument passing to functions (and other callables) works exactly the same way assignment works.

Consider:

def f(x):
    pass
a = 3
b = a
f(a)

b = a means that the target b, in this case a name in the global namespace, becomes a reference to whatever value a references.

f(a) means that the target x, in this case a name in the local namespace of the frame built to execute f, becomes a reference to whatever value a references.

The semantics are identical. Whenever a value gets assigned to a target (which isn't always a simple name—e.g., think lst[0] = a or spam.eggs = a), it follows the same set of assignment rules—whether it's an assignment statement, a function call, an as clause, or a loop iteration variable, there's just one set of rules.


But overall, your intuitive idea that Python is like Java but with only reference types is accurate: You always "pass a reference by value".

Arguing over whether that counts as "pass by reference" or "pass by value" is pointless. Trying to come up with a new unambiguous name for it that nobody will argue about is even more pointless. Liskov invented the term "call by object" three decades ago, and if that never caught on, anything someone comes up with today isn't likely to do any better.

You understand the actual semantics, and that's what matters.


And yes, this means there is no copying. In Java, only primitive values are copied, and Python doesn't have primitive values, so nothing is copied.

the only difference is that 'primitive types'(for example, numbers) are not copied, but simply taken as objects

It's much better to see this as "the only difference is that there are no 'primitive types' (not even simple numbers)", just as you said at the start.


It's also worth asking why Python has no primitive types—or why Java does.2

Making everything "boxed" can be very slow. Adding 2 + 3 in Python means dereferencing the 2 and 3 objects, getting the native values out of them, adding them together, and wrapping the result up in a new 5 object (or looking it up in a table because you already have an existing 5 object). That's a lot more work than just adding two ints.3

While a good JIT like Hotspot—or like PyPy for Python—can often automatically do those optimizations, sometimes "often" isn't good enough. That's why Java has native types: to let you manually optimize things in those cases.

Python, instead, relies on third-party libraries like Numpy, which let you pay the boxing costs just once for a whole array, instead of once per element. Which keeps the language simpler, but at the cost of needing Numpy.4


1. As far as I know, "passed by assignment" appears a couple times in the FAQs, but is not actually used in the reference docs or glossary. The reference docs already lean toward intuitive over rigorous, but the FAQ, like the tutorial, goes much further in that direction. So, asking what a term in the FAQ means, beyond the intuitive idea it's trying to get across, may not be a meaningful question in the first place.

2. I'm going to ignore the issue of Java's lack of operator overloading here. There's no reason they couldn't include special language rules for a handful of core classes, even if they didn't let you do the same thing with your own classes—e.g., Go does exactly that for things like range, and people rarely complain.

3. … or even than looping over two arrays of 30-bit digits, which is what Python actually does. The cost of working on unlimited-size "bigints" is tiny compared to the cost of boxing, so Python just always pays that extra, barely-noticeable cost. Python 2 did, like Java, have separate fixed and bigint types, but a couple decades of experience showed that it wasn't getting any performance benefits out of the extra complexity.

4. The implementation of Numpy is of course far from simple. But using it is pretty simple, and a lot more people need to use Numpy than need to write Numpy, so that turns out to be a pretty decent tradeoff.

Answer from abarnert on Stack Overflow
🌐
GeeksforGeeks
geeksforgeeks.org › python › pass-by-assignment-in-python
Pass by Assignment in Python - GeeksforGeeks
July 23, 2025 - In Python, pass-by-assignment refers to the way function arguments are passed. This means that when a variable is passed to a function, what gets passed is a reference to the object in memory, not the actual object itself.
🌐
Real Python
realpython.com › lessons › pass-by-assignment
Pass by Assignment (Video) – Real Python
00:12 Python doesn’t use either pass by value or pass by reference. It uses something called pass by assignment.
Published: September 21, 2021
Discussions

python - what does it mean by 'passed by assignment'? - Stack Overflow
my understanding of types & parameters passing in java and python: In java, there are primitive types and non-primitive types. Former are not object, latter are objects. In python, they are all More on stackoverflow.com
🌐 stackoverflow.com
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
Python is not pass-by-value, nor is it pass-by-reference. It's actually pass-by-assignment.
The OP is plain wrong. All variables are references in Python, and a function call assigns the arguments to the parameters. If the argument is a constant, the parameter refers to the argument object. If the argument is a variable, the parameter will refer to the same object as the argument. The primitive data types in Python are immutable, which is why reassignment of an int changes the reference and not the object. I teach introductory Python courses and this is about the first concept that is introduced, because it is so fundamental to understanding Python. Also, it is quite different from other programming languages. More on reddit.com
🌐 r/Python
25
0
November 4, 2021
[Python] Pass by reference versus value
Python is neither truly pass by reference or pass by value, although the behavior it resembles closest is passing references by value (but even that's not correct). "Pass by reference" is not some arbitrary term you can make up. If I create a new programming language tomorrow, and say it arguments are passed by reference, there is a very particular behavior you will expect out of my completely new language you've never seen before. Python says it uses "Pass by assignment", but more traditionally, you can refer to it as "pass by object" or "pass by sharing". You can read an Effbot article for clarification, but if that doesn't make any sense, here's my explanation. Consider the following two lines of Python code: x = [] y = x From Python's perspective, there is one object, the empty list. The first line of code takes this name x and binds it to this empty list. The second line, takes this name y and binds it to whatever object is bound to x. That happens to be the empty list. Do you see it? Assignment is a name binding operation. There's an object, and you simply create a new name or take an existing name, and make it refer to said object. So, if we write code like this: y.append(5) print(x) print(y) You get the same output. Why? Because y modifies the same object that x is bound to. But if you do this: y = [1, 2] print(x) print(y) You get two different lists printed out. Why? Because there is now a completely new object, the list [1,2]. And y is now bound to that new list. So, in a function, you need to ask yourself if you do an operation that simply modifies the object, or binds the parameter name to a completely new object. More on reddit.com
🌐 r/learnprogramming
21
5
August 22, 2015
Top answer
1 of 2
24

tl;dr: You're right that Python's semantics are essentially Java's semantics, without any primitive types.


"Passed by assignment" is actually making a different distinction than the one you're asking about.1 The idea is that argument passing to functions (and other callables) works exactly the same way assignment works.

Consider:

def f(x):
    pass
a = 3
b = a
f(a)

b = a means that the target b, in this case a name in the global namespace, becomes a reference to whatever value a references.

f(a) means that the target x, in this case a name in the local namespace of the frame built to execute f, becomes a reference to whatever value a references.

The semantics are identical. Whenever a value gets assigned to a target (which isn't always a simple name—e.g., think lst[0] = a or spam.eggs = a), it follows the same set of assignment rules—whether it's an assignment statement, a function call, an as clause, or a loop iteration variable, there's just one set of rules.


But overall, your intuitive idea that Python is like Java but with only reference types is accurate: You always "pass a reference by value".

Arguing over whether that counts as "pass by reference" or "pass by value" is pointless. Trying to come up with a new unambiguous name for it that nobody will argue about is even more pointless. Liskov invented the term "call by object" three decades ago, and if that never caught on, anything someone comes up with today isn't likely to do any better.

You understand the actual semantics, and that's what matters.


And yes, this means there is no copying. In Java, only primitive values are copied, and Python doesn't have primitive values, so nothing is copied.

the only difference is that 'primitive types'(for example, numbers) are not copied, but simply taken as objects

It's much better to see this as "the only difference is that there are no 'primitive types' (not even simple numbers)", just as you said at the start.


It's also worth asking why Python has no primitive types—or why Java does.2

Making everything "boxed" can be very slow. Adding 2 + 3 in Python means dereferencing the 2 and 3 objects, getting the native values out of them, adding them together, and wrapping the result up in a new 5 object (or looking it up in a table because you already have an existing 5 object). That's a lot more work than just adding two ints.3

While a good JIT like Hotspot—or like PyPy for Python—can often automatically do those optimizations, sometimes "often" isn't good enough. That's why Java has native types: to let you manually optimize things in those cases.

Python, instead, relies on third-party libraries like Numpy, which let you pay the boxing costs just once for a whole array, instead of once per element. Which keeps the language simpler, but at the cost of needing Numpy.4


1. As far as I know, "passed by assignment" appears a couple times in the FAQs, but is not actually used in the reference docs or glossary. The reference docs already lean toward intuitive over rigorous, but the FAQ, like the tutorial, goes much further in that direction. So, asking what a term in the FAQ means, beyond the intuitive idea it's trying to get across, may not be a meaningful question in the first place.

2. I'm going to ignore the issue of Java's lack of operator overloading here. There's no reason they couldn't include special language rules for a handful of core classes, even if they didn't let you do the same thing with your own classes—e.g., Go does exactly that for things like range, and people rarely complain.

3. … or even than looping over two arrays of 30-bit digits, which is what Python actually does. The cost of working on unlimited-size "bigints" is tiny compared to the cost of boxing, so Python just always pays that extra, barely-noticeable cost. Python 2 did, like Java, have separate fixed and bigint types, but a couple decades of experience showed that it wasn't getting any performance benefits out of the extra complexity.

4. The implementation of Numpy is of course far from simple. But using it is pretty simple, and a lot more people need to use Numpy than need to write Numpy, so that turns out to be a pretty decent tradeoff.

2 of 2
1

Similar to passing reference types by value in C#.

Docs: https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/passing-reference-type-parameters#passing-reference-types-by-value

Code demo:

# mutable object
l = [9, 8, 7]


def createNewList(l1: list):
    # l1+[0] will create a new list object, the reference address of the local variable l1 is changed without affecting the variable l
    l1 = l1+[0]


def changeList(l1: list):
    # Add an element to the end of the list, because l1 and l refer to the same object, so l will also change
    l1.append(0)


print(l)
createNewList(l)
print(l)
changeList(l)
print(l)

# immutable object
num = 9


def changeValue(val: int):
    # int is an immutable type, and changing the val makes the val point to the new object 8, 
    # it's not change the num value
    val = 8

print(num)
changeValue(num)
print(num)
🌐
Medium
medium.com › @devyjoneslocker › understanding-pythons-pass-by-assignment-in-the-backdrop-of-pass-by-value-vs-9f5cc602f943
Python : What is it? Pass by Value or Pass by Reference? It is Pass by Assignment | Medium
June 10, 2023 - In conclusion, Python follows a “pass-by-assignment” approach, which combines elements of both “pass-by-value” and “pass-by-reference” behaviors. When passing arguments to functions, Python creates a binding between the function ...
🌐
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's 'pass by assignment' is something in between these two. If you pass a variable name as a function argument, the object this name refers to is assigned to a local variable in the function. This local variable is the parameter name.
🌐
k0nze
k0nze.dev › posts › python-copy-reference-none
Python Course #12: Pass by Assignment, Copy, Reference, and None | k0nze
January 30, 2024 - This mix of pass by value and pass by reference in Python is called pass by assignment.
Find elsewhere
🌐
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.

🌐
LinkedIn
linkedin.com › pulse › pass-assignment-python-what-you-need-know-shrawan-baral
Pass by Assignment in Python: What you need to know
June 20, 2023 - In Python, arguments to a function are passed by assignment. This means that when you call a function, each argument is assigned to a variable in the function's scope.
🌐
Mathspp
mathspp.com › blog › pydonts › pass-by-value-reference-and-assignment
Pass-by-value, reference, and assignment | Pydon't 🐍 | mathspp
November 3, 2021 - When you call a function in Python and give it some arguments... Are they passed by value? No! By reference? No! They're passed by assignment.
🌐
Quora
quora.com › What-is-pass-by-assignment-in-Python
What is pass-by-assignment in Python? - Quora
Answer: (Cross-post from Christopher Reiss's answer to How do you pass by value and pass by reference in Python?) Technically, Python uses “pass by assignment.” This is like call-by-value, in that you can do this : [code]>def plus_1(x) : > x=x+1 > >x=5 >plus_1(x) >print x 5 [/code]Here, ...
🌐
DataCamp
campus.datacamp.com › courses › writing-functions-in-python › best-practices
Pass by assignment | Python
When we assign a list to the variable "my_list", it sets up a location in memory for it. Then, when we pass "my_list" to the function foo(), the parameter "x" gets assigned to that same location.
🌐
Knowledge2life
knowledge2life.com › python › passingmethids.html
Passing Methods in Python-Knowledge2life
Python uses a specific system, which is known as “Call by Object Reference” or “Call by assignment”.When you pass arguments like whole numbers (int, float, etc), strings, or tuple data type to a function, the passing of the function is like call-by-value.
🌐
Real Python
realpython.com › python-pass-by-reference
Pass by Reference in Python: Background and Best Practices – Real Python
March 18, 2026 - Not quite. Python passes arguments neither by reference nor by value, but by assignment. Below, you’ll quickly explore the details of passing by value and passing by reference before looking more closely at Python’s approach.
🌐
Medium
wangyy395.medium.com › pass-by-assignment-in-python-explain-and-practice-49a71864f1f3
Pass by assignment in Python: explain and practice | by Wangyy | Medium
October 11, 2020 - For problem 1, when I pass in a list into a function, it modifies this list in-place, it looks like pass by value. But for problem 2, when I pass in an integer and an object into the function, it doesn’t change at all, it looks like pass by reference. So, what’s the method of passing that Python is using? The answer is: pass by assignment.
🌐
Real Python
realpython.com › lessons › pass-value-reference-python
Pass-By-Value vs Pass-By-Reference in Python (Video) – Real Python
03:49 So, pass-by-assignment is the name we commonly use for this type of argument passing in Python.
Published: July 6, 2021
🌐
Medium
paul-d-chuang.medium.com › python-method-parameters-are-passed-by-assignment-820d949a9c70
Python method parameters are passed by assignment | by Paul Chuang | Medium
May 14, 2024 - If your object is mutable, you pass this object to a method’s parameter but the object has a new assignment, a new object will be created inside the method so the original object works like being passed by value.
🌐
Python
docs.python.org › 3 › faq › programming.html
Programming FAQ — Python 3.14.8 documentation
Remember that arguments are passed by assignment in Python. Since assignment just creates references to objects, there’s no alias between an argument name in the caller and callee, and consequently no call-by-reference.
🌐
GeeksforGeeks
geeksforgeeks.org › python › is-python-call-by-reference-or-call-by-value
Is Python call by reference or call by value - GeeksforGeeks
July 12, 2025 - Passing mutable objects can be considered as call by reference or Python pass by assignment because when their values are changed inside the function, then it will also be reflected outside the function.