Lifehack

Infographic

Counterfeits and copies.

' src=

“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

Counterfeits & Copies (graphic)

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

working remotely

How to Work Remotely (Your Complete Guide)

graham allcott

How to Become a Productivity Ninja by Graham Allcott

time mastery framework

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

how does procrastination affect productivity

The Impact of Procrastination on Productivity

emotions productivity

The Forgotten Emotional Aspects of Productivity

chris bailey lifehack show

How to Calm Your Mind For Hyperfocus by Chris Bailey

misconception of time

8 Misconceptions of Time That Make You Less Productive

time worthy

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

distractions

Distractions: Understanding the Biggest Productivity Killer

work stress

How to Deal With Work Stress in a Healthy Way

time leverage

How to Leverage Time to Make More Time

nighttime anxiety

How Sleep Meditation Can Calm Your Nighttime Anxiety

non toy gifts for kids

30 Meaningful Non-Toy Gifts for Kids This Christmas

power of leverage

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

python assignment reference or copy

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

python assignment reference or copy

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

python assignment reference or copy

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

python assignment reference or copy

How to Increase Mental Focus and Stay Sharp

python assignment reference or copy

How To Learn Faster And Smarter

python assignment reference or copy

How To Get Fit If You Have a Busy Schedule

python assignment reference or copy

How To Boost Energy And Peak Performance

python assignment reference or copy

Level Up Coding

Jeremy Zhang

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

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store

Jeremy Zhang

Hmm…I am a data scientist looking to catch up the tide…

Text to speech

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 ?

Karl Knechtel's user avatar

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.

Hope that clarifies the issue for you.

jamylak's user avatar

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.

newacct's user avatar

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:

Daniel Roseman's user avatar

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

John La Rooy's user avatar

Everything is passed by object. Rebinding and mutating are different operations.

Ignacio Vazquez-Abrams's user avatar

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 .

Hot Network Questions

python assignment reference or copy

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 .

Thawsitt Naing

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:

For compound objects (e.g. a list of lists):

I hope this helped. Feel free to suggest any improvement or fix.

References :

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

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store

Thawsitt Naing

Text to speech

avatar

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

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

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 !

Python snippet containing the code `x is y`.

(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:

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:

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:

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:

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:

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:

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:

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:

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.

Previous Post Next Post

Random Article

Stay in the loop, popular tags.

(You should c|C)heck out this ( awesome)? blog post!+

Mathspp

python assignment reference or copy

Towards Data Science

Weilin Li

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

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 —

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…

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

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store

Coding for therapy

Text to speech

Related Articles

Is Python call by reference or call by value

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...

8 Weeks of LIVE Classes

New Course Launch!

Improve your Coding Skills with Practice

Start your coding journey now.

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

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:

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:

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:

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:

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:

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:

Now here’s what happens if you reassign x to a different 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:

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:

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.

Python Tricks Dictionary Merge

About Marius Mogyorosi

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:

Aldren Santos

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:

Python Logo

5 Thoughts On Python Mastery

🔒 No spam. We take your privacy seriously.

python assignment reference or copy

Learn Python interactively.

Learn Python practically and Get Certified .

Popular Tutorials

Popular examples, reference materials.

Learn Python Interactively

Python Introduction

Python Flow Control

Python Functions

Python Datatypes

Python List

Python Files

Python Object & Class

Python Advanced Topics

Python Date and time

Related Topics

Python List copy()

Python Dictionary copy()

Python Set copy()

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:

To make these copy work, we use the 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

Sorry about that.

Related Tutorials

Python Library

Python Tutorial

Try PRO for FREE

IMAGES

  1. Python Programming Assignment Help & Python Programming Project and Homework Help

    python assignment reference or copy

  2. Python Assignment Operators

    python assignment reference or copy

  3. Python Variables

    python assignment reference or copy

  4. 👍 Python programming assignments. Python Assignment Help: Get Python Assignment Writing Help in

    python assignment reference or copy

  5. Best Quality Python Assignment Help With Fast Delivery

    python assignment reference or copy

  6. Variable Assignment in Python

    python assignment reference or copy

VIDEO

  1. Python Basics Lecture1| Comments| Variables| Datatypes| PythonOnlyGeeks

  2. NPTEL Python for Data Science Week 3 Quiz Answers 2023

  3. Python

  4. Python Introduction

  5. Python

  6. SOLUTION TO GRAND ASSIGNMENT 3 (CCBP) ALL SETS

COMMENTS

  1. What Is a Copy Notation?

    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...

  2. How Do You Use a Copy Machine?

    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.

  3. Counterfeits and Copies

    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...

  4. Understanding Reference and Copy in Python

    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

  5. Python : When is a variable passed by reference and when by value?

    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

  6. Python: Assignment vs Shallow Copy vs Deep Copy

    Assignment Operator (=) ... Assignment with an = on lists does not make a copy. Instead, assignment makes the two variables point to the one list

  7. Python Course #12: Pass by Assignment, Copy, Reference, and None

    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

  8. copy

    Assignment statements in Python do not copy objects, they create bindings between a target and an object. For collections that are mutable or contain

  9. Pass-by-value, reference, and assignment

    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.

  10. Assignment, Shallow Copy, Or Deep 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

  11. Is Python call by reference or call by value

    Python utilizes a system, which is known as “Call by Object Reference” or “Call by assignment”. In the event that you pass arguments like

  12. Variables & Assignment

    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

  13. Pass by Reference in Python: Background and Best Practices

    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

  14. Python Shallow Copy and Deep Copy (With Examples)

    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