

Infographic
Counterfeits and copies.
“I made it in my basement!”
We’ve all made that same dumb joke whenever a cashier checks to make sure our money is real (even though it’s never met with more than a sarcastic chuckle).
All joking aside, the counterfeiting industry is an increasingly large industry that bilks millions of dollars from honest individuals around the world.
In the first half of 2015 alone, over £2.3 million was taken out of circulation across the globe. While you’ll notice cashiers checking for security features when paying with larger bills, £10 and £20 notes are the most commonly counterfeited.
Speaking of security measures, the increase in printing technology has actually aided counterfeiters. Old-fashioned counterfeiting techniques are being used in conjunction with digital printing technology to allow criminals to easily doctor existing bills to appear to be worth more than they really are.
Counterfeiters don’t stop at money, either.
Millions of dollars worth of art, paintings, and other collectibles have been subject to forgery throughout history. Most recently, cases involving phony copies of works by Matisse and Andy Warhol have come to light. Other items such as Pokemon and baseball cards are not immune from potential forgery.
Perhaps most frightening is the idea that over 30,000 fake IDs and passports are currently in circulation at this very moment. Unfortunately, it’s becoming easier and easier for someone to steal your identity without ever coming into contact with you.
And who knows what the future holds? Phony documents and products are becoming easier and easier to make, so officials need to be more diligent than ever. But the real problems lie in the newest mainstream technology: 3D printing. Not only can art be replicated with relative ease, but guns and ammunition are also becoming easier and easier to reproduce.
Hopefully, those who are sworn to protect the public can stay ahead of the technology these criminals are using to gain an advantage with each passing day.
Infographic source: Cartridge Discount

Featured photo credit: Counterfeits and Copies / Cartridge Discount via cartridgediscount.co.uk

How to Work Remotely (Your Complete Guide)

How to Become a Productivity Ninja by Graham Allcott

How to Make Time Work For You — The Time Mastery Framework

The Impact of Procrastination on Productivity

The Forgotten Emotional Aspects of Productivity

How to Calm Your Mind For Hyperfocus by Chris Bailey

8 Misconceptions of Time That Make You Less Productive

Are You Spending Your Time on What Is Time-Worthy?

Distractions: Understanding the Biggest Productivity Killer

How to Deal With Work Stress in a Healthy Way

How to Leverage Time to Make More Time

How Sleep Meditation Can Calm Your Nighttime Anxiety

30 Meaningful Non-Toy Gifts for Kids This Christmas

The Power of Leverage in Leading the Life You Want
6 practical ways to boost your mental fitness.
Productivity
Lifehack Show , Productivity
Procrastination
Focus , Lifehack Show
Explore the Full Life Framework

How to Live a Full Life (Without Compromising on What Truly Matters)

Achieving Goals: The Ultimate Guide to Goal Achieving & Goal Setting in 2022

What Is Motivation And How To Get Motivated (Your Ultimate Guide)

How to Increase Mental Focus and Stay Sharp

How To Learn Faster And Smarter

How To Get Fit If You Have a Busy Schedule

How To Boost Energy And Peak Performance

Level Up Coding
Jun 13, 2021
Understanding Reference and Copy in Python
Referencing, copy, and deepcopy, referencing.
Consider the following case
We created a new variable b and assigned the value of list a to it, after modifying the value in list b , what would be the result of list a and b ?
Consider a second case:
In this example, list a is passed in as an input to our function, and we modified the input inside the function, what would happen to a ?
In both the examples above, you may have guessed, the result of a would be modified un-intentionally.
This is because in both the scenarios above, the new variable that we created actually binds to the same memory address of a , which means although it seems that we created a new variable b , it does not take actual memory space and the new variable was a reference to list a .
An illustrative diagram would be this:
The variable b in the first example and input_list in the second are both pointing to the same address of the variable a , so changing the element would be directly modifying the values in the specific memory address which leads to the changes in a as well.
You can verify the point by printing the memory address of the variables:
So how to address the problem?
Shallow Copy
One way is to use the copy module in python.
This would get the result.
The copy function makes a shallow copy of the original object which separates the original variable a from the new variable b . The line
is basically saying please give me 12 bytes(consider an int takes 4 bytes) of memory and copy the value of a to the new memory address allocated.
But there are problems with shallow copy, see the below example,
What would be the result of a ?
In this scenario, modifying b changes the element in a again, what happened?
The problem with shallow copy is it does not copy a nested object, in this case, it is [1, 2] which is nested in the original list.
Just like the name shallow copy, it only copies the surface instead of delving deep into the recursion, here the third element of b reference back to the original list instead of making a copy. You can verify by printing the memory address of the element.
How to resolve the issue?
A deep copy would go recursively copying an object. Replace the copy with deep copy, you would get:
Here changes made on b would not affect the original variable and the address of a and b would be completely different.
More from Level Up Coding
Coding tutorials and news. The developer homepage gitconnected.com && skilled.dev && levelup.dev
About Help Terms Privacy
Get the Medium app

Jeremy Zhang
Hmm…I am a data scientist looking to catch up the tide…
Text to speech
- Stack Overflow Public questions & answers
- Stack Overflow for Teams Where developers & technologists share private knowledge with coworkers
- Talent Build your employer brand
- Advertising Reach developers & technologists worldwide
- About the company
Collectives™ on Stack Overflow
Find centralized, trusted content and collaborate around the technologies you use most.
Q&A for work
Connect and share knowledge within a single location that is structured and easy to search.
Python : When is a variable passed by reference and when by value? [duplicate]
Why is loc not reference of elements of locs ?
Python : Everything is passed as reference unless explicitly copied [ Is this not True ? ]
Please explain.. how does python decides referencing and copying ?
How to do ?
- locs must contain the final processed response !
- I don't want to use enumerate , is it possible without it ?
- pass-by-reference
- pass-by-value
- 7 Everything is passed by value, but every value is just a reference ;) – wim Mar 14, 2012 at 5:42
6 Answers 6
Effbot (aka Fredrik Lundh) has described Python's variable passing style as call-by-object: http://effbot.org/zone/call-by-object.htm
Objects are allocated on the heap and pointers to them can be passed around anywhere.
- When you make an assignment such as x = 1000 , a dictionary entry is created that maps the string "x" in the current namespace to a pointer to the integer object containing one thousand.
- When you update "x" with x = 2000 , a new integer object is created and the dictionary is updated to point at the new object. The old one thousand object is unchanged (and may or may not be alive depending on whether anything else refers to the object).
- When you do a new assignment such as y = x , a new dictionary entry "y" is created that points to the same object as the entry for "x".
- Objects like strings and integers are immutable . This simply means that there are no methods that can change the object after it has been created. For example, once the integer object one-thousand is created, it will never change. Math is done by creating new integer objects.
- Objects like lists are mutable . This means that the contents of the object can be changed by anything pointing to the object. For example, x = []; y = x; x.append(10); print y will print [10] . The empty list was created. Both "x" and "y" point to the same list. The append method mutates (updates) the list object (like adding a record to a database) and the result is visible to both "x" and "y" (just as a database update would be visible to every connection to that database).
Hope that clarifies the issue for you.

Everything in Python is passed and assigned by value, in the same way that everything is passed and assigned by value in Java. Every value in Python is a reference (pointer) to an object. Objects cannot be values. Assignment always copies the value (which is a pointer); two such pointers can thus point to the same object. Objects are never copied unless you're doing something explicit to copy them.
For your case, every iteration of the loop assigns an element of the list into the variable loc . You then assign something else to the variable loc . All these values are pointers; you're assigning pointers; but you do not affect any objects in any way.
- 1 In my point of view - You described it the best. Just tell me the answer of the Update to the question - that part you missed. – Yugal Jindle Mar 15, 2012 at 5:40
- So what happens with integer and float numbers then? Are they just considered immutable objects? How does python manage that as I'm sure it cannot hold all conceivable numbers in memory ready to be referenced. – Andrew S Apr 23, 2017 at 23:55
- @AndrewS: Integers and floats are indeed immutable (it should be apparent that they do not have methods that mutate themselves). I am not sure what the second part of your comment means. – newacct Apr 28, 2017 at 20:20
- 2 @AndrewS: Maybe they are the same and maybe they aren't. Why does it matter? This has nothing to do with mutability or semantics of assignment. – newacct May 2, 2017 at 6:19
- 1 @AndrewS yes, float and int objects are... objects. And they are immutable. Everything in Python is an object. The behavior of the example you gave is implementation dependant, and could change given any python version, even in minor-version updates. But basically, the CPython compiler will often optimize immutable constant expressions to the same object. How and when it happens depends on a lot of things, and again, is an implementation detail – juanpa.arrivillaga Jul 22, 2020 at 8:13
It doesn't help in Python to think in terms of references or values. Neither is correct.
In Python, variables are just names. In your for loop, loc is just a name that points to the current element in the list. Doing loc = [] simply rebinds the name loc to a different list, leaving the original version alone.
But since in your example, each element is a list, you could actually mutate that element, and that would be reflected in the original list:
- 2 It might be helpful to read Idiomatic Python - "other languages have variables, Python has labels." The rest of it is good reading too. ;) – Li-aung Yip Mar 14, 2012 at 5:50
- How to modify each element of the container ? \ – Yugal Jindle Mar 14, 2012 at 5:54
- @Yugal which part of what I've written above was not clear? – Daniel Roseman Mar 14, 2012 at 5:56
- Generally, I just want to process each element of my container. So, how can that be acheived ? If everything is a label that seems to be a disadvantage when actaully want to edit the element. – Yugal Jindle Mar 14, 2012 at 5:58
- @YugalJindle : To modify elements in a list , use the square brackets to reference items in that list. – Joel Cornett Mar 14, 2012 at 7:00
When you say
you are rebinding the loc variable to a newly created empty list
Perhaps you want
Which assigns a slice (which happens to be the whole list) of loc to the empty list

- 2 I believe this last example is what OP was looking for ! – Anton Belov May 24, 2013 at 8:45
Everything is passed by object. Rebinding and mutating are different operations.
It is . Or at least, it is in the same sense that every other variable in Python is. Python variables are names, not storage . loc is a name that is used to refer to elements of [[1,2], [3,4]] , while locs is a name that refers to the entire structure.
This does not mean "look at the thing that loc names, and cause it to turn into [] ". It cannot mean that, because Python objects are not capable of such a thing.
Instead, it means "cause loc to stop being a name for the thing that it's currently a name for, and start instead being a name for [] ". (Of course, it means the specific [] that's provided there, since in general there may be several objects in memory that are the same.)
Naturally, the contents of locs are unchanged as a result.
Not the answer you're looking for? Browse other questions tagged python reference pass-by-reference pass-by-value or ask your own question .
- The Overflow Blog
- Building an API is half the battle: Q&A with Marco Palladino from Kong
- Developers think AI assistants will be everywhere, but aren’t sure how to...
- Featured on Meta
- We've added a "Necessary cookies only" option to the cookie consent popup
- The Stack Exchange reputation system: What's working? What's not?
- Launching the CI/CD and R Collectives and community editing features for...
- The [amazon] tag is being burninated
- Staging Ground Beta 1 Recap, and Reviewers needed for Beta 2
- Temporary policy: ChatGPT is banned
Hot Network Questions
- Best way to highlight the main result in a mathematical paper
- Is there a "Standard Algorithm" language, as used in academic papers?
- Was Freemasonry such a big problem in 1980s UK policing?
- What is the velocity in the Lorentz equation relative to when considering a vacuum?
- Does the Federal Reserve insure the money of all depositors?
- How was altitude calculated before the invention of the altimeter?
- Are there 2 Parkruns close enough together with a large enough start time difference such that one could run both on one day?
- List all feature classes but exclude those which start with a certain character
- Is post-hyphenation necessary in "I am a child and adult psychologist..."?
- Can a 13-year-old in the UK accept freelance work?
- What is this || notation in BIP 341?
- Some issues with longtable, math coloumn, rowcolor and arraystretch
- Is the Garmin G1000's heading indicator based on a Magnetic compass?
- What if a student doesn't understand a question because of differences in dialect?
- Would it be possible for a planet to orbit around a trinary star system in a figure 8 orbit?
- Clarifications on the Eversmoking Bottle 5e
- Varbinary update attempt
- Who described creative destruction as a process that will eventually balance the jobs created and destroyed?
- On top of itself
- How useful is a caliper for a home-based bike workshop?
- Fired (seemingly) for finding paycheck inconsistencies. What kind of legal recourse might exist?
- What is the "grid" in Bayesian grid approximations?
- What is the concept of hole in semiconductor physics?
- Theoretical Computer Science vs other Sciences?
Your privacy
By clicking “Accept all cookies”, you agree Stack Exchange can store cookies on your device and disclose information in accordance with our Cookie Policy .

Dec 25, 2017
Python: Assignment vs Shallow Copy vs Deep Copy
C opying a list in Python might be trickier than you think. There are 3 ways you can do it: simply using the assignment operator (=), making a shallow copy and making a deep copy. In this article, I will explain what each operation does and how they are different.
Assignment Operator (=)
Assignment with an = on lists does not make a copy. Instead, assignment makes the two variables point to the one list in memory.
So, if you edit the new list, changes will be reflected on the original list.
Easy enough, right? Let’s look at other ways to copy objects.
Before we discuss shallow copy and deep copy, keep in mind that
The difference between shallow and deep copying is only relevant for compound objects (e.g. a list of lists, or class instances) .
Shallow Copy
A shallow copy constructs a new compound object and then (to the extent possible) inserts references into it to the objects found in the original.
It is OK if you find it confusing now. It will make sense soon.
Let’s look at the easy bits first. Here is how you make a shallow copy. In Python 3, you can use list.copy() . However, I prefer the equivalent expression list[:] because it works in both Python 2 and 3.
Shallow copy is different from assignment in that it creates a new object . So, if you make changes to the new list, such as adding or removing items, it won’t affect the original list.
You might think making a shallow copy is simple, BUT here is the tricky part. If the original list is a compound object (e.g. a list of lists), the elements in the new object are referenced to the original elements. (which is why it is called a shallow copy). So, if you modify the mutable elements like lists, the changes will be reflected on the original elements. This will become more clear with an example.
Do you understand the difference between the two examples?
In the first example, we added a new item to b but this change is not reflected on the original list because a and b have separate pointers.
In the second example, we changed the first element of list b and this change is reflected on the original list. This is because the first element b[0] is referenced to a[0] .
List b has its own pointer, but its elements do not. The copied elements in b are pointing to the original elements in a . This is a characteristic of shallow copy. Now, take a look at the definition of shallow copy again and see if it makes sense.
A deep copy constructs a new compound object and then, recursively, inserts copies into it of the objects found in the original.
Again, don’t focus on the definition yet. The deep copy is different from shallow copy in that the copied elements have their own pointers and are not referenced to the original elements. Therefore, no matter how you modify the deep copy, the changes will NOT be reflected on the original list.
Creating a deep copy is slower, because you are making new copies for everything. You will need to import copy module to make a deep copy.
Hopefully, the diagram at the beginning of this article will solidify your understanding. Pay special attention to the pointers, as they are crucial to understand the differences between each operation.
In cPython, you can use id() method to get the address of an object in memory.
This will be helpful for examining the pointer locations of our newly created list objects. Let’s dive right into it.
The best way to understand Python functions is to open a Python shell in your terminal and play around with it. This is how I learn most concepts in Python.
For simple lists such as a list of integers:
- Use assignment = if you want the new changes to affect the original list.
- Use shallow copy [:] if you don’t want the new changes to affect the original list.
For compound objects (e.g. a list of lists):
- Use deep copy if you don’t want the new changes to affect the original list.
- Remember: deep copy makes sure that the newly copied object is not referenced to the original object in any way.
I hope this helped. Feel free to suggest any improvement or fix.
References :
- Google Developers: https://developers.google.com/edu/python/lists
- Python documentation: https://docs.python.org/2/library/copy.html
- Stackoverflow: link
Thawsitt Naing is a senior studying computer science at Stanford University (class of 2019). His interests include Python, web technologies, and machine learning.
More from Thawsitt Naing
About Help Terms Privacy
Get the Medium app

Thawsitt Naing
Text to speech

Python Course #12: Pass by Assignment, Copy, Reference, and None
Now that the you know what mutable (e.g. lists , sets and dictionaries ) and immutable data types (e.g. tuples ) are it is important to talk about copies, references and None .
Python Pass by Assignment
When you call a pass data to a function such as print(...) there are two ways. The first option is to pass the data directly as a value:
The second option is to pass the data as a variable:
The difference between those two options is that the second option allows you to access the data you passed to the function later in your program by stating the variable. When the function that receives the data modifies it internally, you have to be aware of two critical things:
When a primitive data type ( bool , int , float , and str ) or immutable data type (e.g. tuple ) is passed to a function, its value is copied. Therefore, all changes made inside a function won’t affect the values stored in the variables passed to the function. This is called pass by value .
When a mutable data type (e.g. list , set , dict ) is passed to a function, the data isn’t copied. Because of this, changes that are made inside the function affect the values outside of the function. This is called pass by reference
This sounds pretty theoretical, so here comes an example:
Even though you haven’t learned about declaring functions in Python this example declares the function func(x, y) that takes two parameters. func(x, y) subtracts 1 from the first parameter, and calls pop() on the second one. That is everything you need to understand at the moment.
In the main program, the int i and the list l are declared and then passed to func(x, y) . When looking at i and l after func(x, y) has been executed, you can see that i is still 1 and not 0 because i ’s value was copied. However, l is missing its last element since it was passed as a reference.
This mix of pass by value and pass by reference in Python is called pass by assignment . It is essential to keep this concept always in mind when writing Python code.
In the previous parts of this Python course, you have seen that it is possible to get a copy of a mutable data type by calling the .copy() function:
By using .copy() , the data outside of the function isn’t changed.
In the following example the difference between a copy and reference is further amplified:
In the first line the list ['a', 'b', 'c'] is declared and than a new reference to this list is created with l = . In the second line another reference to the list ['a', 'b', 'c'] is created with: m = l . In the third line the list is copied and a reference to that copy is created with: n = l.copy() .
There are three references to two lists with the same content. l and m reference the first list and n reference the second list . Because l and m reference the same list every modification done using l or m will always be reflected in both. n won’t change as it references a different list .
Python is vs ==
To check if two variables reference the same value you can use the is operator to compare the values use the == operator:
l is n evaluates to False because they reference differnt list s, however, those two list s contain the same values and therefore l == n evaluates to True . You can also check the id that a variable is referencing using id(...) :
You can see that the id of l and m is the same and the id of n is different (The numbers are different everytime you run this code). The is operator is actually implemented using == with id(...) == id(...) .
Python None
Now that you know the difference between a copy and a reference, there is one last thing to talk about: ` None . The keyword None in Python indicates no value at all. And there is only one None`:
None can be used to initialize a variable without assigning a value. This can be useful when the value of a variable is assigned under a condition:
None actually has it’s own type and is an immutable data type because it can’t be changed:
None concludes this article. Throughout this Python course, you will come across pass by assignment, copies, references, and None reasonably often. Make sure to get the free Python Sets Cheat Sheet in my Gumroad shop . If you have any questions about this article, feel free to join our Discord community to ask them over there.
Further Reading
Python course #14: user input.
Now that you know how to use for and while loops in Python, you can start getting input from outside of your program. In this article, you will learn how to capture a user’s input and build a small...
Python Course #15: Reading and Writing Files
So far, you can store data within the variables of a program; however, when the program ends, this data is gone. And when you start the program again, all the data you want to work with has to be e...
Python Course #16: Functions
Up until now you have used a lot of functions already, most prominently the print(...) function. Now it is time to write your own functions in Python. {% youtube_embed “3Cec5C7s42A” %} What is a ...
Estimate Gas in Ethereum Transactions with Python web3 and brownie
Change Windows 10/11 Display Resolution with a Python System Tray Application
Trending Tags
- Python »
- 3.11.2 Documentation »
- The Python Standard Library »
- Data Types »
- copy — Shallow and deep copy operations
copy — Shallow and deep copy operations ¶
Source code: Lib/copy.py
Assignment statements in Python do not copy objects, they create bindings between a target and an object. For collections that are mutable or contain mutable items, a copy is sometimes needed so one can change one copy without changing the other. This module provides generic shallow and deep copy operations (explained below).
Interface summary:
Return a shallow copy of x .
Return a deep copy of x .
Raised for module specific errors.
The difference between shallow and deep copying is only relevant for compound objects (objects that contain other objects, like lists or class instances):
A shallow copy constructs a new compound object and then (to the extent possible) inserts references into it to the objects found in the original.
A deep copy constructs a new compound object and then, recursively, inserts copies into it of the objects found in the original.
Two problems often exist with deep copy operations that don’t exist with shallow copy operations:
Recursive objects (compound objects that, directly or indirectly, contain a reference to themselves) may cause a recursive loop.
Because deep copy copies everything it may copy too much, such as data which is intended to be shared between copies.
The deepcopy() function avoids these problems by:
keeping a memo dictionary of objects already copied during the current copying pass; and
letting user-defined classes override the copying operation or the set of components copied.
This module does not copy types like module, method, stack trace, stack frame, file, socket, window, or any similar types. It does “copy” functions and classes (shallow and deeply), by returning the original object unchanged; this is compatible with the way these are treated by the pickle module.
Shallow copies of dictionaries can be made using dict.copy() , and of lists by assigning a slice of the entire list, for example, copied_list = original_list[:] .
Classes can use the same interfaces to control copying that they use to control pickling. See the description of module pickle for information on these methods. In fact, the copy module uses the registered pickle functions from the copyreg module.
In order for a class to define its own copy implementation, it can define special methods __copy__() and __deepcopy__() . The former is called to implement the shallow copy operation; no additional arguments are passed. The latter is called to implement the deep copy operation; it is passed one argument, the memo dictionary. If the __deepcopy__() implementation needs to make a deep copy of a component, it should call the deepcopy() function with the component as first argument and the memo dictionary as second argument. The memo dictionary should be treated as an opaque object.
Discussion of the special methods used to support object state retrieval and restoration.
Previous topic
types — Dynamic type creation and names for built-in types
pprint — Data pretty printer
- Report a Bug
- Show Source
Pass-by-value, reference, and assignment | Pydon't 🐍
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.
Want to improve your Python 🐍 problem-solving skills? The Python Problem-Solving Bootcamp is just starting! Join now !

(If you are new here and have no idea what a Pydon't is, you may want to read the Pydon't Manifesto .)
Introduction
Many traditional programming languages employ either one of two models when passing arguments to functions:
- some languages use the pass-by-value model; and
- most of the others use the pass-by-reference model.
Having said that, it is important to know the model that Python uses, because that influences the way your code behaves.
In this Pydon't, you will:
- see that Python doesn't use the pass-by-value nor the pass-by-reference models;
- understand that Python uses a pass-by-assignment model;
- learn about the built-in function id ;
- create a better understanding for the Python object model;
- realise that every object has 3 very important properties that define it;
- understand the difference between mutable and immutable objects;
- learn the difference between shallow and deep copies; and
- learn how to use the module copy to do both types of object copies.
You can now get your free copy of the ebook “Pydon'ts – Write beautiful Python code” on Gumroad .
Is Python pass-by-value?
In the pass-by-value model, when you call a function with a set of arguments, the data is copied into the function. This means that you can modify the arguments however you please and that you won't be able to alter the state of the program outside the function. This is not what Python does, Python does not use the pass-by-value model.
Looking at the snippet of code that follows, it might look like Python uses pass-by-value:
This looks like the pass-by-value model because we gave it a 3, changed it to a 4, and the change wasn't reflected on the outside ( a is still 3).
But, in fact, Python is not copying the data into the function.
To prove this, I'll show you a different function:
As we can see, the list l , that was defined outside of the function, changed after calling the function clearly_not_pass_by_value . Hence, Python does not use a pass-by-value model.
Is Python pass-by-reference?
In a true pass-by-reference model, the called function gets access to the variables of the callee! Sometimes, it can look like that's what Python does, but Python does not use the pass-by-reference model.
I'll do my best to explain why that's not what Python does:
If Python used a pass-by-reference model, the function would've managed to completely change the value of l outside the function, but that's not what happened, as we can see.
Let me show you an actual pass-by-reference situation.
Here's some Pascal code:
Look at the last lines of that code:
- we assign 2 to x with x := 2 ;
- we print x ;
- we call foo with x as argument; and
- we print x again.
What's the output of this program?
I imagine that most of you won't have a Pascal interpreter lying around, so you can just go to tio.run and run this code online
If you run this, you'll see that the output is
which can be rather surprising, if the majority of your programming experience is in Python!
The procedure foo effectively received the variable x and changed the value that it contained. After foo was done, the variable x (that lives outside foo ) had a different value. You can't do anything like this in Python.
Python object model
To really understand the way Python behaves when calling functions, it's best if we first understand what Python objects are, and how to characterise them.
The three characteristics of objects
In Python, everything is an object, and each object is characterised by three things:
- its identity (an integer that uniquely identifies the object, much like social security numbers identify people);
- a type (that identifies the operations you can do with your object); and
- the object's content.
Here is an object and its three characteristics:
As we can see above, id is the built-in function you use to query the identity of an object, and type is the built-in function you use to query the type of an object.
(Im)mutability
The (im)mutability of an object depends on its type. In other words, (im)mutability is a characteristic of types, not of specific objects!
But what exactly does it mean for an object to be mutable? Or for an object to be immutable?
Recall that an object is characterised by its identity, its type, and its contents. A type is mutable if you can change the contents of its objects without changing its identity and its type.
Lists are a great example of a mutable data type. Why? Because lists are containers : you can put things inside lists and you can remove stuff from inside those same lists.
Below, you can see how the contents of the list obj change as we make method calls, but the identity of the list remains the same:
However, when dealing with immutable objects, it's a completely different story. If we check an English dictionary, this is what we get for the definition of “immutable”:
adjective: immutable – unchanging over time or unable to be changed.
Immutable objects' contents never change. Take a string as an example:
Strings are a good example for this discussion because, sometimes, they can look mutable. But they are not!
A very good indicator that an object is immutable is when all its methods return something. This is unlike list's .append method, for example! If you use .append on a list, you get no return value. On the other hand, whatever method you use on a string, the result is returned to you:
Notice how obj wasn't updated automatically to "HELLO, WORLD!" . Instead, the new string was created and returned to you.
Another great hint at the fact that strings are immutable is that you cannot assign to its indices:
This shows that, when a string is created, it remains the same. It can be used to build other strings, but the string itself always. stays. unchanged.
As a reference, int , float , bool , str , tuple , and complex are the most common types of immutable objects; list , set , and dict are the most common types of mutable objects.
Variable names as labels
Another important thing to understand is that a variable name has very little to do with the object itself.
In fact, the name obj was just a label that I decided to attach to the object that has identity 2698212637504, has the list type, and contents 1, 2, 3.
Just like I attached the label obj to that object, I can attach many more names to it:
Again, these names are just labels. Labels that I decided to stick to the same object. How can we know it's the same object? Well, all their “social security numbers” (the ids) match, so they must be the same object:
Therefore, we conclude that foo , bar , baz , and obj , are variable names that all refer to the same object.
The operator is
This is exactly what the operator is does: it checks if the two objects are the same .
For two objects to be the same, they must have the same identity:
It is not enough to have the same type and contents! We can create a new list with contents [1, 2, 3] and that will not be the same object as obj :
Think of it in terms of perfect twins. When two siblings are perfect twins, they look identical. However, they are different people!
Just as a side note, but an important one, you should be aware of the operator is not .
Generally speaking, when you want to negate a condition, you put a not in front of it:
So, if you wanted to check if two variables point to different objects, you could be tempted to write
However, Python has the operator is not , which is much more similar to a proper English sentence, which I think is really cool!
Therefore, the example above should actually be written
Python does a similar thing for the in operator, providing a not in operator as well... How cool is that?!
Assignment as nicknaming
If we keep pushing this metaphor forward, assigning variables is just like giving a new nickname to someone.
My friends from middle school call me “Rojer”. My friends from college call me “Girão”. People I am not close to call me by my first name – “Rodrigo”. However, regardless of what they call me, I am still me , right?
If one day I decide to change my haircut, everyone will see the new haircut, regardless of what they call me!
In a similar fashion, if I modify the contents of an object, I can use whatever nickname I prefer to see that those changes happened. For example, we can change the middle element of the list we have been playing around with:
We used the nickname foo to modify the middle element, but that change is visible from all other nicknames as well.
Because they all pointed at the same list object.

Python is pass-by-assignment
Having laid out all of this, we are now ready to understand how Python passes arguments to functions.
When we call a function, each of the parameters of the function is assigned to the object they were passed in. In essence, each parameter now becomes a new nickname to the objects that were given in.
Immutable arguments
If we pass in immutable arguments, then we have no way of modifying the arguments themselves. After all, that's what immutable means: “doesn't change”.
That is why it can look like Python uses the pass-by-value model. Because the only way in which we can have the parameter hold something else is by assigning it to a completely different thing. When we do that, we are reusing the same nickname for a different object:
In the example above, when we call foo with the argument 5 , it's as if we were doing bar = 5 at the beginning of the function.
Immediately after that, we have bar = 3 . This means “take the nickname "bar" and point it at the integer 3 ”. Python doesn't care that bar , as a nickname (as a variable name) had already been used. It is now pointing at that 3 !
Mutable arguments
On the other hand, mutable arguments can be changed. We can modify their internal contents. A prime example of a mutable object is a list: its elements can change (and so can its length).
That is why it can look like Python uses a pass-by-reference model. However, when we change the contents of an object, we didn't change the identity of the object itself. Similarly, when you change your haircut or your clothes, your social security number does not change:
Do you understand what I'm trying to say? If not, drop a comment below and I'll try to help.
Beware when calling functions
This goes to show you should be careful when defining your functions. If your function expects mutable arguments, you should do one of the two:
- do not mutate the argument in any way whatsoever; or
- document explicitly that the argument may be mutated.
Personally, I prefer to go with the first approach: to not mutate the argument; but there are times and places for the second approach.
Sometimes, you do need to take the argument as the basis for some kind of transformation, which would mean you would want to mutate the argument. In those cases, you might think about doing a copy of the argument (discussed in the next section), but making that copy can be resource intensive. In those cases, mutating the argument might be the only sensible choice.
Making copies
Shallow vs deep copies.
“Copying an object” means creating a second object that has a different identity (therefore, is a different object) but that has the same contents. Generally speaking, we copy one object so that we can work with it and mutate it, while also preserving the first object.
When copying objects, there are a couple of nuances that should be discussed.
Copying immutable objects
The first thing that needs to be said is that, for immutable objects, it does not make sense to talk about copies.
“Copies” only make sense for mutable objects. If your object is immutable, and if you want to preserve a reference to it, you can just do a second assignment and work on it:
Or, sometimes, you can just call methods and other functions directly on the original, because the original is not going anywhere:
So, we only need to worry about mutable objects.
Shallow copy
Many mutable objects can contain, themselves, mutable objects. Because of that, two types of copies exist:
- shallow copies; and
- deep copies.
The difference lies in what happens to the mutable objects inside the mutable objects.
Lists and dictionaries have a method .copy that returns a shallow copy of the corresponding object.
Let's look at an example with a list:
First, we create a list inside a list, and we copy the outer list. Now, because it is a copy , the copied list isn't the same object as the original outer list:
But if they are not the same object, then we can modify the contents of one of the lists, and the other won't reflect the change:
That's what we saw: we changed the first element of the copy_list , and the outer_list remained unchanged.
Now, we try to modify the contents of sublist , and that's when the fun begins!
When we modify the contents of sublist , both the outer_list and the copy_list reflect those changes...
But wasn't the copy supposed to give me a second list that I could change without affecting the first one? Yes! And that is what happened!
In fact, modifying the contents of sublist doesn't really modify the contents of neither copy_list nor outer_list : after all, the third element of both was pointing at a list object, and it still is! It's the (inner) contents of the object to which we are pointing that changed.
Sometimes, we don't want this to happen: sometimes, we don't want mutable objects to share inner mutable objects.
Common shallow copy techniques
When working with lists, it is common to use slicing to produce a shallow copy of a list:
Using the built-in function for the respective type, on the object itself, also builds shallow copies. This works for lists and dictionaries, and is likely to work for other mutable types.
Here is an example with a list inside a list:
And here is an example with a list inside a dictionary:
When you want to copy an object “thoroughly”, and you don't want the copy to share references to inner objects, you need to do a “deep copy” of your object. You can think of a deep copy as a recursive algorithm.
You copy the elements of the first level and, whenever you find a mutable element on the first level, you recurse down and copy the contents of those elements.
To show this idea, here is a simple recursive implementation of a deep copy for lists that contain other lists:
We can use this function to copy the previous outer_list and see what happens:
As you can see here, modifying the contents of sublist only affected outer_list indirectly; it didn't affect copy_list .
Sadly, the list_deepcopy method I implemented isn't very robust, nor versatile, but the Python Standard Library has got us covered!
The module copy and the method deepcopy
The module copy is exactly what we need. The module provides two useful functions:
- copy.copy for shallow copies; and
- copy.deepcopy for deep copies.
And that's it! And, what is more, the method copy.deepcopy is smart enough to handle issues that might arise with circular definitions, for example! That is, when an object contains another that contains the first one: a naïve recursive implementation of a deep copy algorithm would enter an infinite loop!
If you write your own custom objects and you want to specify how shallow and deep copies of those should be made, you only need to implement __copy__ and __deepcopy__ , respectively!
It's a great module, in my opinion.
Examples in code
Now that we have gone deep into the theory – pun intended –, it is time to show you some actual code that plays with these concepts.
Mutable default arguments
Let's start with a Twitter favourite:
Python 🐍 is an incredible language but sometimes appears to have quirks 🤪 For example, one thing that often confuses beginners is why you shouldn't use lists as default values 👇 Here is a thread 👇🧵 that will help you understand this 💯 pic.twitter.com/HVhPjS2PSH — Rodrigo 🐍📝 (@mathsppblog) October 5, 2021
Apparently, it's a bad idea to use mutable objects as default arguments. Here is a snippet showing you why:
The function above appends an element to a list and, if no list is given, appends it to an empty list by default.
Great, let's put this function to good use:
We use it once with 1 , and we get a list with the 1 inside. Then, we use it to append a 1 to another list we had. And finally, we use it to append a 3 to an empty list... Except that's not what happens!
As it turns out, when we define a function, the default arguments are created and stored in a special place:
What this means is that the default argument is always the same object. Therefore, because it is a mutable object, its contents can change over time. That is why, in the code above, __defaults__ shows a list with two items already.
If we redefine the function, then its __defaults__ shows an empty list:
This is why, in general, mutable objects shouldn't be used as default arguments.
The standard practice, in these cases, is to use None and then use Boolean short-circuiting to assign the default value:
With this implementation, the function now works as expected:
is not None
Searching through the Python Standard Library shows that the is not operator is used a bit over 5,000 times. That's a lot.
And, by far and large, that operator is almost always followed by None . In fact, is not None appears 3169 times in the standard library!
x is not None does exactly what it's written: it checks if x is None or not.
Here is a simple example usage of that, from the argparse module to create command line interfaces:
Even without a great deal of context, we can see what is happening: when displaying command help for a given section, we may want to indent it (or not) to show hierarchical dependencies.
If a section's parent is None , then that section has no parent, and there is no need to indent. In other words, if a section's parent is not None , then we want to indent it. Notice how my English matches the code exactly!
Deep copy of the system environment
The method copy.deepcopy is used a couple of times in the standard library, and here I'd like to show an example usage where a dictionary is copied.
The module os provides the attribute environ , similar to a dictionary, that contains the environment variables that are defined.
Here are a couple of examples from my (Windows) machine:
The module http.server provides some classes for basic HTTP servers.
One of those classes, CGIHTTPRequestHandler , implements a HTTP server that can also run CGI scripts and, in its run_cgi method, it needs to set a bunch of environment variables.
These environment variables are set to give the necessary context for the CGI script that is going to be ran. However, we don't want to actually modify the current environment!
So, what we do is create a deep copy of the environment, and then we modify it to our heart's content! After we are done, we tell Python to execute the CGI script, and we provide the altered environment as an argument.
The exact way in which this is done may not be trivial to understand. I, for one, don't think I could explain it to you. But that doesn't mean we can't infer parts of it:
Here is the code:
As we can see, we copied the environment and defined some variables. Finally, we created a new subprocess that gets the modified environment.
Here's the main takeaway of this Pydon't, for you, on a silver platter:
“ Python uses a pass-by-assignment model, and understanding it requires you to realise all objects are characterised by an identity number, their type, and their contents. ”
This Pydon't showed you that:
- Python doesn't use the pass-by-value model, nor the pass-by-reference one;
- Python uses a pass-by-assignment model (using “nicknames”);
- its identity;
- its type; and
- its contents.
- the id function is used to query an object's identifier;
- the type function is used to query an object's type;
- the type of an object determines whether it is mutable or immutable;
- shallow copies copy the reference of nested mutable objects;
- deep copies perform copies that allow one object, and its inner elements, to be changed without ever affecting the copy;
- copy.copy and copy.deepcopy can be used to perform shallow/deep copies; and
- you can implement __copy__ and __deepcopy__ if you want your own objects to be copiable.
If you prefer video content, you can check this YouTube video , which was inspired by this article.
If you liked this Pydon't be sure to leave a reaction below and share this with your friends and fellow Pythonistas. Also, subscribe to the newsletter so you don't miss a single Pydon't!
Thanks for reading ❤️
I hope you learned something new! If you did, consider following the footsteps of the readers who bought me a slice of pizza 🍕 . Your contribution boosts my confidence and helps me produce this content for you.
- Python 3 Docs, Programming FAQ, “How do I write a function with output parameters (call by reference)?”, https://docs.python.org/3/faq/programming.html#how-do-i-write-a-function-with-output-parameters-call-by-reference [last accessed 04-10-2021];
- Python 3 Docs, The Python Standard Library, copy , https://docs.python.org/3/library/copy.html [last accessed 05-10-2021];
- effbot.org, “Call by Object” (via “arquivo.pt”), https://arquivo.pt/wayback/20160516131553/http://effbot.org/zone/call-by-object.htm [last accessed 04-10-2021];
- effbot.org, “Python Objects” (via “arquivo.pt”), https://arquivo.pt/wayback/20191115002033/http://effbot.org/zone/python-objects.htm [last accessed 04-10-2021];
- Robert Heaton, “Is Python pass-by-reference or pass-by-value”, https://robertheaton.com/2014/02/09/pythons-pass-by-object-reference-as-explained-by-philip-k-dick/ [last accessed 04-10-2021];
- StackOverflow question and answers, “How do I pass a variable by reference?”, https://stackoverflow.com/q/986006/2828287 [last accessed 04-10-2021];
- StackOverflow question and answers, “Passing values in Python [duplicate]”, https://stackoverflow.com/q/534375/2828287 [last accessed 04-10-2021];
- Twitter thread by @mathsppblog , https://twitter.com/mathsppblog/status/1445148566721335298 [last accessed 20-10-2021];
Previous Post Next Post
Random Article
Stay in the loop, popular tags.
- 4 March 2023
- 3 February 2023
- 5 January 2023
- 1 December 2022
- 1 November 2022
- 3 September 2022
- 1 August 2022
- 7 July 2022
- 5 June 2022
- 6 April 2022
- 11 March 2022
(You should c|C)heck out this ( awesome)? blog post!+


Towards Data Science

Nov 24, 2019
Assignment, Shallow Copy, Or Deep Copy?
A story about python’s memory management.
The goal of this article is to describe what will happen in memory when we
- Assign a variable B = A ,
- Shallow copy it C = copy(A) , or
- Deep copy it D = deepcopy(A) .
I first describe a bit about memory management and optimization in Python. After laying the ground, I explain the difference between assignment statement, shallow copy, and deep copy. I then summarize the difference in a table.
If you prefer watching a video to reading an article, you can find the complementary video here .
Memory Management In Python
int , float , list , dict , class instances , … they are all objects in Python. In CPython implementation, built-in function id() returns memory address of an object —
If we create a new variable L2 that refers to an object with the same value as L1 , L2 will have a new memory address —
Every time a new object is created, it will have a new memory address. Except when it is —
- a very short string
- an integer within [-5, 256]
- an empty immutable containers (e.g. tuples)
Let’s see an example with an integer object. Both x and y refer to the same value 10. While L1 and L2 in the previous example had two different memory addresses, x and y share the same memory address —
That’s because, in those three exceptions, Python optimizes memory by having the second variable refer to the same object in memory, — some call it “shared object”.
Keep the concept of shared object in mind because we’ll need it later when we create a deepcopy of an object.
Variable Assignment
It says in the Python documentation that “Assignment statements in Python do not copy objects, they create bindings between a target and an object.” That means when we create a variable by assignment, the new variable refers to the same object as the original variable does —
Because the new variable B and the original variable A share the same object (i.e. the same list), they also contain same elements —
As illustrated in the figure below, A and B share the same id , i.e., they refer to the same object in memory. And they contain the same elements as well.
Shallow Copy
When we create a variable by shallow copy , the new variable refers to a new object —
Although A and C refers to two different objects (i.e. two lists with different memory addresses), elements in the two lists refer to the same objects —
The figure below illustrates how elements in A refer to same objects as elements in C .
Similar to shallow copy, when we create a variable by deep copy , the new variable refers to a new object —
As described in Python documentation —
The difference between shallow and deep copying is only relevant for compound objects (objects that contain other objects, like lists or class instances): - A shallow copy constructs a new compound object and then (to the extent possible) inserts references into it to the objects found in the original. - A deep copy constructs a new compound object and then, recursively, inserts copies into it of the objects found in the original.
So different from shallow copy, elements in the two lists now refer to different objects —
But why do A[0] and D[0] share the same object (i.e. have the same memory address)? Because they both refer to integers, which is one of the three exceptions due to memory optimization we mentioned in the beginning.
The figure below shows A and D refer to two different lists in memory, and elements in A refer to different objects than elements in D except integer elements due to memory optimization.
If there is one take-away from this article, it must be the table below. Variable assignment doesn’t copy objects, so A and B have the same memory address and contain same elements. Shallow copy creates a new object for C , but elements in C still refer to the same objects as elements in A . Deep copy also creates a new object for D , and elements in D refer to different objects than those elements in A with three types of exceptions.
This article is inspired by…
- Python documentation on copy
- Understanding Python variables and Memory Management
More from Towards Data Science
Your home for data science. A Medium publication sharing concepts, ideas and codes.
About Help Terms Privacy
Get the Medium app

Coding for therapy
Text to speech
- Data Structure & Algorithm Classes (Live)
- System Design (Live)
- DevOps(Live)
- Explore More Live Courses
- Interview Preparation Course
- Data Science (Live)
- GATE CS & IT 2024
- Data Structure & Algorithm-Self Paced(C++/JAVA)
- Data Structures & Algorithms in Python
- Explore More Self-Paced Courses
- C++ Programming - Beginner to Advanced
- Java Programming - Beginner to Advanced
- C Programming - Beginner to Advanced
- Full Stack Development with React & Node JS(Live)
- Java Backend Development(Live)
- Android App Development with Kotlin(Live)
- Python Backend Development with Django(Live)
- Complete Data Science Program(Live)
- Mastering Data Analytics
- DevOps Engineering - Planning to Production
- CBSE Class 12 Computer Science
- School Guide
- All Courses
- Linked List
- Binary Tree
- Binary Search Tree
- Advanced Data Structure
- All Data Structures
- Asymptotic Analysis
- Worst, Average and Best Cases
- Asymptotic Notations
- Little o and little omega notations
- Lower and Upper Bound Theory
- Analysis of Loops
- Solving Recurrences
- Amortized Analysis
- What does 'Space Complexity' mean ?
- Pseudo-polynomial Algorithms
- Polynomial Time Approximation Scheme
- A Time Complexity Question
- Searching Algorithms
- Sorting Algorithms
- Graph Algorithms
- Pattern Searching
- Geometric Algorithms
- Mathematical
- Bitwise Algorithms
- Randomized Algorithms
- Greedy Algorithms
- Dynamic Programming
- Divide and Conquer
- Backtracking
- Branch and Bound
- All Algorithms
- Company Preparation
- Practice Company Questions
- Interview Experiences
- Experienced Interviews
- Internship Interviews
- Competitive Programming
- Design Patterns
- System Design Tutorial
- Multiple Choice Quizzes
- Go Language
- Tailwind CSS
- Foundation CSS
- Materialize CSS
- Semantic UI
- Angular PrimeNG
- Angular ngx Bootstrap
- jQuery Mobile
- jQuery EasyUI
- React Bootstrap
- React Rebass
- React Desktop
- React Suite
- ReactJS Evergreen
- ReactJS Reactstrap
- BlueprintJS
- TensorFlow.js
- English Grammar
- School Programming
- Number System
- Trigonometry
- Probability
- Mensuration
- Class 8 Syllabus
- Class 9 Syllabus
- Class 10 Syllabus
- Class 11 Syllabus
- Class 8 Notes
- Class 9 Notes
- Class 10 Notes
- Class 11 Notes
- Class 12 Notes
- Class 8 Formulas
- Class 9 Formulas
- Class 10 Formulas
- Class 11 Formulas
- Class 8 Maths Solution
- Class 9 Maths Solution
- Class 10 Maths Solution
- Class 11 Maths Solution
- Class 12 Maths Solution
- Class 7 Notes
- History Class 7
- History Class 8
- History Class 9
- Geo. Class 7
- Geo. Class 8
- Geo. Class 9
- Civics Class 7
- Civics Class 8
- Business Studies (Class 11th)
- Microeconomics (Class 11th)
- Statistics for Economics (Class 11th)
- Business Studies (Class 12th)
- Accountancy (Class 12th)
- Macroeconomics (Class 12th)
- Machine Learning
- Data Science
- Mathematics
- Operating System
- Computer Networks
- Computer Organization and Architecture
- Theory of Computation
- Compiler Design
- Digital Logic
- Software Engineering
- GATE 2024 Live Course
- GATE Computer Science Notes
- Last Minute Notes
- GATE CS Solved Papers
- GATE CS Original Papers and Official Keys
- GATE CS 2023 Syllabus
- Important Topics for GATE CS
- GATE 2023 Important Dates
- Software Design Patterns
- HTML Cheat Sheet
- CSS Cheat Sheet
- Bootstrap Cheat Sheet
- JS Cheat Sheet
- jQuery Cheat Sheet
- Angular Cheat Sheet
- Facebook SDE Sheet
- Amazon SDE Sheet
- Apple SDE Sheet
- Netflix SDE Sheet
- Google SDE Sheet
- Wipro Coding Sheet
- Infosys Coding Sheet
- TCS Coding Sheet
- Cognizant Coding Sheet
- HCL Coding Sheet
- FAANG Coding Sheet
- Love Babbar Sheet
- Mass Recruiter Sheet
- Product-Based Coding Sheet
- Company-Wise Preparation Sheet
- Array Sheet
- String Sheet
- Graph Sheet
- ISRO CS Original Papers and Official Keys
- ISRO CS Solved Papers
- ISRO CS Syllabus for Scientist/Engineer Exam
- UGC NET CS Notes Paper II
- UGC NET CS Notes Paper III
- UGC NET CS Solved Papers
- Campus Ambassador Program
- School Ambassador Program
- Geek of the Month
- Campus Geek of the Month
- Placement Course
- Testimonials
- Student Chapter
- Geek on the Top
- Geography Notes
- History Notes
- Science & Tech. Notes
- Ethics Notes
- Polity Notes
- Economics Notes
- UPSC Previous Year Papers
- SSC CGL Syllabus
- General Studies
- Subjectwise Practice Papers
- Previous Year Papers
- SBI Clerk Syllabus
- General Awareness
- Quantitative Aptitude
- Reasoning Ability
- SBI Clerk Practice Papers
- SBI PO Syllabus
- SBI PO Practice Papers
- IBPS PO 2022 Syllabus
- English Notes
- Reasoning Notes
- Mock Question Papers
- IBPS Clerk Syllabus
- Apply for a Job
- Apply through Jobathon
- Hire through Jobathon
- All DSA Problems
- Problem of the Day
- GFG SDE Sheet
- Top 50 Array Problems
- Top 50 String Problems
- Top 50 Tree Problems
- Top 50 Graph Problems
- Top 50 DP Problems
- Solving For India-Hackthon
- GFG Weekly Coding Contest
- Job-A-Thon: Hiring Challenge
- BiWizard School Contest
- All Contests and Events
- Saved Videos
- What's New ?
- Data Structures
- Interview Preparation
- Topic-wise Practice
- Latest Blogs
- Write & Earn
- Web Development
Related Articles
- Write Articles
- Pick Topics to write
- Guidelines to Write
- Get Technical Writing Internship
- Write an Interview Experience
- Pass by reference vs value in Python
Is Python call by reference or call by value
- Mutable vs Immutable Objects in Python
- G-Fact 19 (Logical and Bitwise Not Operators on Boolean)
- Ternary Operator in Python
- Division Operators in Python
- Operator Overloading in Python
- Any All in Python
- Operator Functions in Python | Set 1
- Operator Functions in Python | Set 2
- Difference between == and is operator in Python
- Python Membership and Identity Operators
- Python | Set 3 (Strings, Lists, Tuples, Iterations)
- Python String
- Python Lists
- Python Tuples
- Python Sets
- Python Dictionary
- Python Arrays
- Python | Using 2D arrays/lists the right way
- Multi-dimensional lists in Python
- Convert Python Nested Lists to Multidimensional NumPy Arrays
- Convert Python List to numpy Arrays
- Adding new column to existing DataFrame in Pandas
- Python map() function
- Read JSON file using Python
- How to get column names in Pandas dataframe
- Taking input in Python
- Read a file line by line in Python
- Difficulty Level : Easy
- Last Updated : 19 Apr, 2021
Python utilizes a system, which is known as “Call by Object Reference” or “Call by assignment”. In the event that you pass arguments like whole numbers, strings or tuples to a function, the passing is like call-by-value because you can not change the value of the immutable objects being passed to the function. Whereas passing mutable objects can be considered as call by reference because when their values are changed inside the function, then it will also be reflected outside the function. Example 1:
Output
Example 2
Output
Binding Names to Objects
In python, each variable to which we assign a value/container is treated as an object. When we are assigning a value to a variable, we are actually binding a name to an object .
Now, let’s try and understand this better with another example. Example 2:
The output of the above two examples are different because the list is mutable and the string is immutable . An immutable variable cannot be changed once created. If we wish to change an immutable variable, such as a string, we must create a new instance and bind the variable to the new instance. Whereas, mutable variable can be changed in place. Example 3:
Output:
In the above example, a string which is an immutable type of object is passed as argument to the function foo. Within the scope of the given function foo, a= “new value” has been bounded to the same object that string has been bound outside. Within the scope of the function foo, we modify “old value”` to “new value”. Once we leave the scope of function foo , a=”new value” is no longer in the name space, and the value that string refers to was never changed. Example 4: Now, let us look at how mutable variable is passed into the function.
Output:
When we pass a mutable variable into the function foo and modify it to some other name the function foo still points to that object and continue to point to that object during its execution.
Please Login to comment...
- simmytarika5
- python-basics
8 Weeks of LIVE Classes
New Course Launch!
Improve your Coding Skills with Practice
Start your coding journey now.
- Module 2: The Essentials of Python »
- Variables & Assignment
- View page source
Variables & Assignment
There are reading-comprehension exercises included throughout the text. These are meant to help you put your reading to practice. Solutions for the exercises are included at the bottom of this page.
Variables permit us to write code that is flexible and amendable to repurpose. Suppose we want to write code that logs a student’s grade on an exam. The logic behind this process should not depend on whether we are logging Brian’s score of 92% versus Ashley’s score of 94%. As such, we can utilize variables, say name and grade , to serve as placeholders for this information. In this subsection, we will demonstrate how to define variables in Python.
In Python, the = symbol represents the “assignment” operator. The variable goes to the left of = , and the object that is being assigned to the variable goes to the right:
Attempting to reverse the assignment order (e.g. 92 = name ) will result in a syntax error. When a variable is assigned an object (like a number or a string), it is common to say that the variable is a reference to that object. For example, the variable name references the string "Brian" . This means that, once a variable is assigned an object, it can be used elsewhere in your code as a reference to (or placeholder for) that object:
Valid Names for Variables
A variable name may consist of alphanumeric characters ( a-z , A-Z , 0-9 ) and the underscore symbol ( _ ); a valid name cannot begin with a numerical value.
var : valid
_var2 : valid
ApplePie_Yum_Yum : valid
2cool : invalid (begins with a numerical character)
I.am.the.best : invalid (contains . )
They also cannot conflict with character sequences that are reserved by the Python language. As such, the following cannot be used as variable names:
for , while , break , pass , continue
in , is , not
if , else , elif
def , class , return , yield , raises
import , from , as , with
try , except , finally
There are other unicode characters that are permitted as valid characters in a Python variable name, but it is not worthwhile to delve into those details here.
Mutable and Immutable Objects
The mutability of an object refers to its ability to have its state changed. A mutable object can have its state changed, whereas an immutable object cannot. For instance, a list is an example of a mutable object. Once formed, we are able to update the contents of a list - replacing, adding to, and removing its elements.
To spell out what is transpiring here, we:
Create (initialize) a list with the state [1, 2, 3] .
Assign this list to the variable x ; x is now a reference to that list.
Using our referencing variable, x , update element-0 of the list to store the integer -4 .
This does not create a new list object, rather it mutates our original list. This is why printing x in the console displays [-4, 2, 3] and not [1, 2, 3] .
A tuple is an example of an immutable object. Once formed, there is no mechanism by which one can change of the state of a tuple; and any code that appears to be updating a tuple is in fact creating an entirely new tuple.
Mutable & Immutable Types of Objects
The following are some common immutable and mutable objects in Python. These will be important to have in mind as we start to work with dictionaries and sets.
Some immutable objects
numbers (integers, floating-point numbers, complex numbers)
“frozen”-sets
Some mutable objects
dictionaries
NumPy arrays
Referencing a Mutable Object with Multiple Variables
It is possible to assign variables to other, existing variables. Doing so will cause the variables to reference the same object:
What this entails is that these common variables will reference the same instance of the list. Meaning that if the list changes, all of the variables referencing that list will reflect this change:
We can see that list2 is still assigned to reference the same, updated list as list1 :
In general, assigning a variable b to a variable a will cause the variables to reference the same object in the system’s memory, and assigning c to a or b will simply have a third variable reference this same object. Then any change (a.k.a mutation ) of the object will be reflected in all of the variables that reference it ( a , b , and c ).
Of course, assigning two variables to identical but distinct lists means that a change to one list will not affect the other:
Reading Comprehension: Does slicing a list produce a reference to that list?
Suppose x is assigned a list, and that y is assigned a “slice” of x . Do x and y reference the same list? That is, if you update part of the subsequence common to x and y , does that change show up in both of them? Write some simple code to investigate this.
Reading Comprehension: Understanding References
Based on our discussion of mutable and immutable objects, predict what the value of y will be in the following circumstance:
Reading Comprehension Exercise Solutions:
Does slicing a list produce a reference to that list?: Solution
Based on the following behavior, we can conclude that slicing a list does not produce a reference to the original list. Rather, slicing a list produces a copy of the appropriate subsequence of the list:
Understanding References: Solutions
Integers are immutable, thus x must reference an entirely new object ( 9 ), and y still references 3 .

Pass by Reference in Python: Background and Best Practices
Table of Contents
Defining Pass by Reference
Contrasting pass by reference and pass by value, avoiding duplicate objects, returning multiple values, creating conditional multiple-return functions, understanding assignment in python, exploring function arguments, best practice: return and reassign, best practice: use object attributes, best practice: use dictionaries and lists.
Watch Now This tutorial has a related video course created by the Real Python team. Watch it together with the written tutorial to deepen your understanding: Pass by Reference in Python: Best Practices
After gaining some familiarity with Python, you may notice cases in which your functions don’t modify arguments in place as you might expect, especially if you’re familiar with other programming languages. Some languages handle function arguments as references to existing variables , which is known as pass by reference . Other languages handle them as independent values , an approach known as pass by value .
If you’re an intermediate Python programmer who wishes to understand Python’s peculiar way of handling function arguments, then this tutorial is for you. You’ll implement real use cases of pass-by-reference constructs in Python and learn several best practices to avoid pitfalls with your function arguments.
In this tutorial, you’ll learn:
- What it means to pass by reference and why you’d want to do so
- How passing by reference differs from both passing by value and Python’s unique approach
- How function arguments behave in Python
- How you can use certain mutable types to pass by reference in Python
- What the best practices are for replicating pass by reference in Python
Free Bonus: 5 Thoughts On Python Mastery , a free course for Python developers that shows you the roadmap and the mindset you’ll need to take your Python skills to the next level.
Before you dive into the technical details of passing by reference, it’s helpful to take a closer look at the term itself by breaking it down into components:
- Pass means to provide an argument to a function.
- By reference means that the argument you’re passing to the function is a reference to a variable that already exists in memory rather than an independent copy of that variable.
Since you’re giving the function a reference to an existing variable, all operations performed on this reference will directly affect the variable to which it refers. Let’s look at some examples of how this works in practice.
Below, you’ll see how to pass variables by reference in C#. Note the use of the ref keyword in the highlighted lines:
As you can see, the refParameter of squareRef() must be declared with the ref keyword, and you must also use the keyword when calling the function. Then the argument will be passed in by reference and can be modified in place.
Python has no ref keyword or anything equivalent to it. If you attempt to replicate the above example as closely as possible in Python, then you’ll see different results:
In this case, the arg variable is not altered in place. It seems that Python treats your supplied argument as a standalone value rather than a reference to an existing variable. Does this mean Python passes arguments by value rather than by reference?
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. After that, you’ll walk through some best practices for achieving the equivalent of passing by reference in Python.
When you pass function arguments by reference, those arguments are only references to existing values. In contrast, when you pass arguments by value, those arguments become independent copies of the original values.
Let’s revisit the C# example, this time without using the ref keyword. This will cause the program to use the default behavior of passing by value:
Here, you can see that squareVal() doesn’t modify the original variable. Rather, valParameter is an independent copy of the original variable arg . While that matches the behavior you would see in Python, remember that Python doesn’t exactly pass by value. Let’s prove it.
Python’s built-in id() returns an integer representing the memory address of the desired object. Using id() , you can verify the following assertions:
- Function arguments initially refer to the same address as their original variables.
- Reassigning the argument within the function gives it a new address while the original variable remains unmodified.
In the below example, note that the address of x initially matches that of n but changes after reassignment, while the address of n never changes:
The fact that the initial addresses of n and x are the same when you invoke increment() proves that the x argument is not being passed by value. Otherwise, n and x would have distinct memory addresses.
Before you learn the details of how Python handles arguments, let’s take a look at some practical use cases of passing by reference.
Using Pass by Reference Constructs
Passing variables by reference is one of several strategies you can use to implement certain programming patterns. While it’s seldom necessary, passing by reference can be a useful tool.
In this section, you’ll look at three of the most common patterns for which passing by reference is a practical approach. You’ll then see how you can implement each of these patterns with Python.
As you’ve seen, passing a variable by value will cause a copy of that value to be created and stored in memory. In languages that default to passing by value, you may find performance benefits from passing the variable by reference instead, especially when the variable holds a lot of data. This will be more apparent when your code is running on resource-constrained machines.
In Python, however, this is never a problem. You’ll see why in the next section .
One of the most common applications of passing by reference is to create a function that alters the value of the reference parameters while returning a distinct value. You can modify your pass-by-reference C# example to illustrate this technique:
In the example above, greet() returns a greeting string and also modifies the value of counter . Now try to reproduce this as closely as possible in Python:
counter isn’t incremented in the above example because, as you’ve previously learned, Python has no way of passing values by reference. So how can you achieve the same outcome as you did with C#?
In essence, reference parameters in C# allow the function not only to return a value but also to operate on additional parameters. This is equivalent to returning multiple values!
Luckily, Python already supports returning multiple values. Strictly speaking, a Python function that returns multiple values actually returns a tuple containing each value:
As you can see, to return multiple values, you can simply use the return keyword followed by comma-separated values or variables.
Armed with this technique, you can change the return statement in greet() from your previous Python code to return both a greeting and a counter:
That still doesn’t look right. Although greet() now returns multiple values, they’re being printed as a tuple , which isn’t your intention. Furthermore, the original counter variable remains at 0 .
To clean up your output and get the desired results, you’ll have to reassign your counter variable with each call to greet() :
Now, after reassigning each variable with a call to greet() , you can see the desired results!
Assigning return values to variables is the best way to achieve the same results as passing by reference in Python. You’ll learn why, along with some additional methods, in the section on best practices .
This is a specific use case of returning multiple values in which the function can be used in a conditional statement and has additional side effects like modifying an external variable that was passed in as an argument.
Consider the standard Int32.TryParse function in C#, which returns a Boolean and operates on a reference to an integer argument at the same time:
This function attempts to convert a string into a 32-bit signed integer using the out keyword . There are two possible outcomes:
- If parsing succeeds , then the output parameter will be set to the resulting integer, and the function will return true .
- If parsing fails , then the output parameter will be set to 0 , and the function will return false .
You can see this in practice in the following example, which attempts to convert a number of different strings:
The above code, which attempts to convert differently formatted strings into integers via TryParse() , outputs the following:
To implement a similar function in Python, you could use multiple return values as you’ve seen previously:
This tryparse() returns two values. The first value indicates whether the conversion was successful, and the second holds the result (or None , in case of failure).
However, using this function is a little clunky because you need to unpack the return values with every call. This means you can’t use the function within an if statement :
Even though it generally works by returning multiple values, tryparse() can’t be used in a condition check. That means you have some more work to do.
You can take advantage of Python’s flexibility and simplify the function to return a single value of different types depending on whether the conversion succeeds:
With the ability for Python functions to return different data types, you can now use this function within a conditional statement. But how? Wouldn’t you have to call the function first, assigning its return value, and then check the value itself?
By taking advantage of Python’s flexibility in object types, as well as the new assignment expressions in Python 3.8, you can call this simplified function within a conditional if statement and get the return value if the check passes:
Wow! This Python version of tryparse() is even more powerful than the C# version, allowing you to use it within conditional statements and in arithmetic expressions.
With a little ingenuity, you’ve replicated a specific and useful pass-by-reference pattern without actually passing arguments by reference. In fact, you are yet again assigning return values when using the assignment expression operator( := ) and using the return value directly in Python expressions.
So far, you’ve learned what passing by reference means, how it differs from passing by value, and how Python’s approach is different from both. Now you’re ready to take a closer look at how Python handles function arguments!
Passing Arguments in Python
Python passes arguments by assignment. That is, when you call a Python function, each function argument becomes a variable to which the passed value is assigned.
Therefore, you can learn important details about how Python handles function arguments by understanding how the assignment mechanism itself works, even outside functions.
Python’s language reference for assignment statements provides the following details:
- If the assignment target is an identifier, or variable name, then this name is bound to the object. For example, in x = 2 , x is the name and 2 is the object.
- If the name is already bound to a separate object, then it’s re-bound to the new object. For example, if x is already 2 and you issue x = 3 , then the variable name x is re-bound to 3 .
All Python objects are implemented in a particular structure. One of the properties of this structure is a counter that keeps track of how many names have been bound to this object.
Note: This counter is called a reference counter because it keeps track of how many references, or names, point to the same object. Do not confuse reference counter with the concept of passing by reference, as the two are unrelated.
The Python documentation provides additional details on reference counts .
Let’s stick to the x = 2 example and examine what happens when you assign a value to a new variable:
- If an object representing the value 2 already exists, then it’s retrieved. Otherwise, it’s created.
- The reference counter of this object is incremented.
- An entry is added in the current namespace to bind the identifier x to the object representing 2 . This entry is in fact a key-value pair stored in a dictionary ! A representation of that dictionary is returned by locals() or globals() .
Now here’s what happens if you reassign x to a different value:
- The reference counter of the object representing 2 is decremented.
- The reference counter of the object that represents the new value is incremented.
- The dictionary for the current namespace is updated to relate x to the object representing the new value.
Python allows you to obtain the reference counts for arbitrary values with the function sys.getrefcount() . You can use it to illustrate how assignment increases and decreases these reference counters. Note that the interactive interpreter employs behavior that will yield different results, so you should run the following code from a file:
This script will show the reference counts for each value prior to assignment, after assignment, and after reassignment:
These results illustrate the relationship between identifiers (variable names) and Python objects that represent distinct values. When you assign multiple variables to the same value, Python increments the reference counter for the existing object and updates the current namespace rather than creating duplicate objects in memory.
In the next section, you’ll build upon your current understanding of assignment operations by exploring how Python handles function arguments.
Function arguments in Python are local variables . What does that mean? Local is one of Python’s scopes . These scopes are represented by the namespace dictionaries mentioned in the previous section. You can use locals() and globals() to retrieve the local and global namespace dictionaries, respectively.
Upon execution, each function has its own local namespace:
Using locals() , you can demonstrate that function arguments become regular variables in the function’s local namespace. Let’s add an argument, my_arg , to the function:
You can also use sys.getrefcount() to show how function arguments increment the reference counter for an object:
The above script outputs reference counts for "my_value" first outside, then inside show_refcount() , showing a reference count increase of not one, but two!
That’s because, in addition to show_refcount() itself, the call to sys.getrefcount() inside show_refcount() also receives my_arg as an argument. This places my_arg in the local namespace for sys.getrefcount() , adding an extra reference to "my_value" .
By examining namespaces and reference counts inside functions, you can see that function arguments work exactly like assignments: Python creates bindings in the function’s local namespace between identifiers and Python objects that represent argument values. Each of these bindings increments the object’s reference counter.
Now you can see how Python passes arguments by assignment!
Replicating Pass by Reference With Python
Having examined namespaces in the previous section, you may be asking why global hasn’t been mentioned as one way to modify variables as if they were passed by reference:
Using the global statement generally takes away from the clarity of your code. It can create a number of issues, including the following:
- Free variables, seemingly unrelated to anything
- Functions without explicit arguments for said variables
- Functions that can’t be used generically with other variables or arguments since they rely on a single global variable
- Lack of thread safety when using global variables
Contrast the previous example with the following, which explicitly returns a value:
Much better! You avoid all potential issues with global variables, and by requiring an argument, you make your function clearer.
Despite being neither a pass-by-reference language nor a pass-by-value language, Python suffers no shortcomings in that regard. Its flexibility more than meets the challenge.
You’ve already touched on returning values from the function and reassigning them to a variable. For functions that operate on a single value, returning the value is much clearer than using a reference. Furthermore, since Python already uses pointers behind the scenes, there would be no additional performance benefits even if it were able to pass arguments by reference.
Aim to write single-purpose functions that return one value, then (re)assign that value to variables, as in the following example:
Returning and assigning values also makes your intention explicit and your code easier to understand and test.
For functions that operate on multiple values, you’ve already seen that Python is capable of returning a tuple of values . You even surpassed the elegance of Int32.TryParse() in C# thanks to Python’s flexibility!
If you need to operate on multiple values, then you can write single-purpose functions that return multiple values, then (re)assign those values to variables. Here’s an example:
When calling a function that returns multiple values, you can assign multiple variables at the same time.
Object attributes have their own place in Python’s assignment strategy. Python’s language reference for assignment statements states that if the target is an object’s attribute that supports assignment, then the object will be asked to perform the assignment on that attribute. If you pass the object as an argument to a function, then its attributes can be modified in place.
Write functions that accept objects with attributes, then operate directly on those attributes, as in the following example:
Note that square() needs to be written to operate directly on an attribute, which will be modified without the need to reassign a return value.
It’s worth repeating that you should make sure the attribute supports assignment! Here’s the same example with namedtuple , whose attributes are read-only:
Attempts to modify attributes that don’t allow modification result in an AttributeError .
Additionally, you should be mindful of class attributes. They will remain unchanged, and an instance attribute will be created and modified:
Since class attributes remain unchanged when modified through a class instance, you’ll need to remember to reference the instance attribute.
Dictionaries in Python are a different object type than all other built-in types. They’re referred to as mapping types . Python’s documentation on mapping types provides some insight into the term:
A mapping object maps hashable values to arbitrary objects. Mappings are mutable objects. There is currently only one standard mapping type, the dictionary. ( Source )
This tutorial doesn’t cover how to implement a custom mapping type, but you can replicate pass by reference using the humble dictionary. Here’s an example using a function that operates directly on dictionary elements:
Since you’re reassigning a value to a dictionary key, operating on dictionary elements is still a form of assignment. With dictionaries, you get the added practicality of accessing the modified value through the same dictionary object.
While lists aren’t mapping types, you can use them in a similar way to dictionaries because of two important characteristics: subscriptability and mutability . These characteristics are worthy of a little more explanation, but let’s first take a look at best practices for mimicking pass by reference using Python lists.
To replicate pass by reference using lists, write a function that operates directly on list elements:
Since you’re reassigning a value to an element within the list, operating on list elements is still a form of assignment. Similar to dictionaries, lists allow you to access the modified value through the same list object.
Now let’s explore subscriptability. An object is subscriptable when a subset of its structure can be accessed by index positions:
Lists, tuples, and strings are subscriptable, but sets are not. Attempting to access an element of an object that isn’t subscriptable will raise a TypeError .
Mutability is a broader topic requiring additional exploration and documentation reference . To keep things short, an object is mutable if its structure can be changed in place rather than requiring reassignment:
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. Function arguments become local variables assigned to each value that was passed to the function. But this doesn’t prevent you from achieving the same results you’d expect when passing arguments by reference in other languages.
In this tutorial, you learned:
- How Python handles assigning values to variables
- How function arguments are passed by assignment in Python
- Why returning values is a best practice for replicating pass by reference
- How to use attributes , dictionaries , and lists as alternative best practices
You also learned some additional best practices for replicating pass-by-reference constructs in Python. You can use this knowledge to implement patterns that have traditionally required support for passing by reference.
To continue your Python journey, I encourage you to dive deeper into some of the related topics that you’ve encountered here, such as mutability , assignment expressions , and Python namespaces and scope .
Stay curious, and see you next time!
🐍 Python Tricks 💌
Get a short & sweet Python Trick delivered to your inbox every couple of days. No spam ever. Unsubscribe any time. Curated by the Real Python team.

About Marius Mogyorosi

Marius is a tinkerer who loves using Python for creative projects within and beyond the software security field.
Each tutorial at Real Python is created by a team of developers so that it meets our high quality standards. The team members who worked on this tutorial are:

Master Real-World Python Skills With Unlimited Access to Real Python
Join us and get access to thousands of tutorials, hands-on video courses, and a community of expert Pythonistas:
Join us and get access to thousands of tutorials, hands-on video courses, and a community of expert Pythonistas:
What Do You Think?
What’s your #1 takeaway or favorite thing you learned? How are you going to put your newfound skills to use? Leave a comment below and let us know.
Commenting Tips: The most useful comments are those written with the goal of learning from or helping out other students. Get tips for asking good questions and get answers to common questions in our support portal . Looking for a real-time conversation? Visit the Real Python Community Chat or join the next “Office Hours” Live Q&A Session . Happy Pythoning!
Keep Learning
Related Tutorial Categories: best-practices intermediate python
Recommended Video Course: Pass by Reference in Python: Best Practices
Keep reading Real Python by creating a free account or signing in:
Already have an account? Sign-In
Almost there! Complete this form and click the button below to gain instant access:

5 Thoughts On Python Mastery
🔒 No spam. We take your privacy seriously.
Learn Python interactively.
Learn Python practically and Get Certified .
Popular Tutorials
Popular examples, reference materials.
Learn Python Interactively
Python Introduction
- Getting Started
- Keywords and Identifier
- Python Comments
- Python Variables
- Python Data Types
- Python Type Conversion
- Python I/O and Import
- Python Operators
- Python Namespace
Python Flow Control
- Python if...else
- Python for Loop
- Python while Loop
- Python break and continue
- Python Pass
Python Functions
- Python Function
- Function Argument
- Python Recursion
- Anonymous Function
- Global, Local and Nonlocal
- Python Global Keyword
- Python Modules
- Python Package
Python Datatypes
- Python Numbers
Python List
- Python Tuple
- Python String
- Python Dictionary
Python Files
- Python File Operation
- Python Directory
- Python Exception
- Exception Handling
- User-defined Exception
Python Object & Class
- Classes & Objects
- Python Inheritance
- Multiple Inheritance
- Operator Overloading
Python Advanced Topics
- Python Iterator
- Python Generator
- Python Closure
- Python Decorators
- Python Property
- Python RegEx
- Python Examples
Python Date and time
- Python datetime Module
- Python datetime.strftime()
- Python datetime.strptime()
- Current date & time
- Get current time
- Timestamp to datetime
- Python time Module
- Python time.sleep()
Related Topics
Python List copy()
Python Dictionary copy()
Python Set copy()
- Python Lambda/Anonymous Function
- Python List Comprehension
Python Shallow Copy and Deep Copy
In this article, you’ll learn about shallow copy and deep copy in Python with the help of examples.
Copy an Object in Python
In Python, we use = operator to create a copy of an object. You may think that this creates a new object; it doesn't. It only creates a new variable that shares the reference of the original object.
Let's take an example where we create a list named old_list and pass an object reference to new_list using = operator.
Example 1: Copy using = operator
When we run above program, the output will be:
As you can see from the output both variables old_list and new_list shares the same id i.e 140673303268168 .
So, if you want to modify any values in new_list or old_list , the change is visible in both.
Essentially, sometimes you may want to have the original values unchanged and only modify the new values or vice versa. In Python, there are two ways to create copies:
- Shallow Copy
To make these copy work, we use the copy module.
- Copy Module
We use the copy module of Python for shallow and deep copy operations. Suppose, you need to copy the compound list say x . For example:
Here, the copy() return a shallow copy of x . Similarly, deepcopy() return a deep copy of x .
A shallow copy creates a new object which stores the reference of the original elements.
So, a shallow copy doesn't create a copy of nested objects, instead it just copies the reference of nested objects. This means, a copy process does not recurse or create copies of nested objects itself.
Example 2: Create a copy using shallow copy
When we run the program , the output will be:
In above program, we created a nested list and then shallow copy it using copy() method.
This means it will create new and independent object with same content. To verify this, we print the both old_list and new_list .
To confirm that new_list is different from old_list , we try to add new nested object to original and check it.
Example 3: Adding [4, 4, 4] to old_list, using shallow copy
When we run the program, it will output:
In the above program, we created a shallow copy of old_list . The new_list contains references to original nested objects stored in old_list . Then we add the new list i.e [4, 4, 4] into old_list . This new sublist was not copied in new_list .
However, when you change any nested objects in old_list , the changes appear in new_list .
Example 4: Adding new nested object using Shallow copy
In the above program, we made changes to old_list i.e old_list[1][1] = 'AA' . Both sublists of old_list and new_list at index [1][1] were modified. This is because, both lists share the reference of same nested objects.
A deep copy creates a new object and recursively adds the copies of nested objects present in the original elements.
Let’s continue with example 2. However, we are going to create deep copy using deepcopy() function present in copy module. The deep copy creates independent copy of original object and all its nested objects.
Example 5: Copying a list using deepcopy()
In the above program, we use deepcopy() function to create copy which looks similar.
However, if you make changes to any nested objects in original object old_list , you’ll see no changes to the copy new_list .
Example 6: Adding a new nested object in the list using Deep copy
In the above program, when we assign a new value to old_list , we can see only the old_list is modified. This means, both the old_list and the new_list are independent. This is because the old_list was recursively copied, which is true for all its nested objects.
Table of Contents
- Copy an Object in Python
Sorry about that.
Related Tutorials
Python Library
Python Tutorial
Try PRO for FREE

IMAGES
VIDEO
COMMENTS
A copy notation is a type of end notation to a formal letter. A copy notation is a list of people that ought to receive a copy of the letter. It is a reminder that other people, besides the addressed recipient, have an interest in the lette...
Place your paper on the scanner or in the document feeder, if there are several pages. Then, select the number of copies and other settings. Print the copies and remove the originals from the copier.
Counterfeiting is becoming easier and easier as technology continues to improve. A passionate writer who shares lifestlye tips on Lifehack Read full profile “I made it in my basement!”We’ve all made that same dumb joke whenever a cashier ch...
Just like the name shallow copy, it only copies the surface instead of delving deep into the recursion, here the third element of b reference back to the
Every value in Python is a reference (pointer) to an object. Objects cannot be values. Assignment always copies the value (which is a pointer); two such
Assignment Operator (=) ... Assignment with an = on lists does not make a copy. Instead, assignment makes the two variables point to the one list
Python Pass by Assignment · When a primitive data type ( bool , int , float , and str ) or immutable data type (e.g. tuple ) is passed to a
Assignment statements in Python do not copy objects, they create bindings between a target and an object. For collections that are mutable or contain
Is Python pass-by-value? ... In the pass-by-value model, when you call a function with a set of arguments, the data is copied into the function.
- A shallow copy constructs a new compound object and then (to the extent possible) inserts references into it to the objects found in the
Python utilizes a system, which is known as “Call by Object Reference” or “Call by assignment”. In the event that you pass arguments like
Referencing a Mutable Object with Multiple Variables · to a variable · will cause the variables to reference the same object in the system's memory, and
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
In Python, we use = operator to create a copy of an object. You may think that this creates a new object; it doesn't. It only creates a new variable that