Loading video player…

Understanding Object Copying

Resource linked in this lesson: Differences Between Python’s Mutable and Immutable Types

00:00 Before getting to the main course of copying objects in Python, this lesson serves as kind of an appetizer. First off, you should consider some motivations for object copying.

00:10 Then, what are the characteristics of these Python objects you’ll be copying? And key to understanding copying, how does Python handle references and values?

00:21 So what is object copying? Copying an object creates a duplicate of that object in memory, and crucially allows you to modify both objects independently of one another.

00:32 So what? Why would I want to do that, you ask? Well, while far from an exhaustive list, here are a few of the reasons you might want to copy an object—protecting sensitive data from modification.

00:44 For example, a class that represents a bank account would do well to provide access to copies of its data, like the account balance, and not allow direct access and potential mutation.

00:55 Creating new objects based on an existing object, if you needed to modify an object while still retaining the original for comparison, for example. Sharing data across multiple processes.

01:06 If you’re working with concurrency and multiple processes, you often want each process to have its own copy of whatever data they need to access. And these are just a few of the ways it can be useful to work with copies instead of originals.

01:20 Let’s also talk about the characteristics of Python objects. In the context of copying, there are a couple of really important distinctions between different types of objects in Python.

01:30 The first is they can be scalar or composite. Scalar data types represent indivisible atomic values. You can’t break them down into constituent parts. On the other hand, composite data types are containers made up of other elements and their members can themselves also be scalar or composite, which allows for a kind of nesting to exist.

01:52 The second distinction is that objects can be mutable or immutable. Mutable objects can be altered after creation. For example, lists, which support adding and removing elements.

02:03 Immutable objects are unchangeable and read-only once defined, like tuples, which are fixed and can’t be modified. And it’s important to note that these characteristics are unconnected to each other.

02:14 You can think of them as existing on separate axes.

02:19 See this table for a few examples of the different types found in each category.

02:24 There are no built-in types that are both mutable and scalar, which makes sense. You can, however, theoretically implement your own. For immutable scalar types, you can look to the int, float and bool types among many others.

02:40 Examples of mutable, that is changeable composite types include the list, set and the dict types, all of which can have elements added or removed after you create them.

02:50 To see cases of composite and immutable objects, look at the tuple and frozenset types, both of which cannot be modified after creation.

03:00 I’ll also ask you to note that these distinctions are not always clear-cut. For example, in some cases the str data type behaves as an indivisible scalar, but in other cases, it behaves as a composite list of characters.

03:14 There is much more to discuss about mutability and immutability, but in another course. Which course? Well, I recommend Differences Between Python’s Mutable and Immutable Types.

03:26 But for this lesson, one more thing. References versus values. In programming, it’s important to distinguish between references and values. Values are actual data stored in memory, and they can be scalar or composite.

03:40 References are memory addresses pointing to stored values.

03:43 Some operations will work with values while other operations will work with references. This will be especially key when we get to discussing shallow and deep copies.

03:53 And in Python specifically, variables are references to objects and not containers that hold values.

04:01 The assignment operation does not copy data. Instead, it binds a name to an existing object like adding a label. And multiple labels can be associated with the same object in memory.

04:13 And in that case, it makes them aliases, not copies of that object.

04:18 Pop open the REPL, and let’s take a look at an example of this.

04:23 Start by creating a mutable composite object. A list holding the integers one through four: numbers = [1, 2, 3, 4].

04:33 Then create a new variable called digits and assign numbers to it. digits = numbers. Examine digits, the list: [1, 2, 3, 4]. So now you have two variables, digits and numbers.

04:47 They may appear to be copies, but they’re actually aliases of each other. How can you tell? Use the is operator to compare their identities. is will return True if both of its operands refer to the same object.

05:02 digits is numbers returns True. So they share an identity. What does this mean? Go ahead and modify digits. Set the first element to zero using assignment: digits[0] = 0. Look at digits again,

05:18 [0, 2, 3, 4]. Now look at numbers also: [0, 2, 3, 4]. See? Modifying digits also modified numbers because they both referenced the same object.

05:32 One more way to verify this is using the built-in id() function, which returns a unique integer for any given object in memory: id (digits), id(numbers).

05:44 The numbers you see will probably be different from the numbers on my screen, but the numbers themselves don’t matter. What’s important is that the two numbers are the same.

05:53 In this case they are, which means digits and numbers, again, reference the same object. So if your goal is to make copies, this is not very useful, is it?

06:03 To see how to make an actual copy, follow me to the next lesson.

Become a Member to join the conversation.