Placing objects in memory

Any time we place something like [2, 3, 4] or "hello" or 123456123 in our program, the corresponding object is placed into memory. For example, the following: a = "hello"

Places the string "hello" in memory, and assigned the address where "hello" was stored to a. We can find that address using id(a).

Placing mutable objects in memory

Consider the following:

In [1]:
a = "CSC180"
b = "CSC180"
print(id(a))
print(id(b))
140121299555416
140121299555416

a and b refer to the same address. That's because Python saw that they refer to the same string, and decided to save space by not placing "CSC180" in two separate memory slots.

Since strings are immutable (i.e., their content cannot be changed), there is no danger here, even though a and b are aliases of each other. Since we cannot change the contents of a (we can, of course, make a refer to a new string), there is no danger that changing the contents of a will also change the contents of b.

Python is not always smart enough to save memory space that way

In [2]:
d = "CSC"
e = "180"
f = d + e  #f == "CSC180"
print(id(a))
print(id(b))
print(id(f))
140121299555416
140121299555416
140121299557376

Even though the we could theoretically figure out that f can have the same id as a and b, this was not done, and there are now two copies of the string "CSC180" in memory.

What about integers? Python (or rather CPython, the version of Python we are using) always knows to find integers between -5 and 256, but may place larger (and smaller) integers in many places in memory.

Here is a fun thing to do: let's display the id's of integers between -10 and 299:

In [3]:
#Cannot do this with for i in range(-10, 300) directly because
#python keeps recreating the integers and putting them in 
#different memory locations
nums = list(range(-10, 300))
for i in nums:
    print(i,  id(i), id(i+1)-id(i))
-10 140121329127088 -29615328
-9 140121299510256 1440
-8 140121299510416 1344
-7 140121299510384 1312
-6 140121299510064 -140121289514768
-5 9995296 32
-4 9995328 32
-3 9995360 32
-2 9995392 32
-1 9995424 32
0 9995456 32
1 9995488 32
2 9995520 32
3 9995552 32
4 9995584 32
5 9995616 32
6 9995648 32
7 9995680 32
8 9995712 32
9 9995744 32
10 9995776 32
11 9995808 32
12 9995840 32
13 9995872 32
14 9995904 32
15 9995936 32
16 9995968 32
17 9996000 32
18 9996032 32
19 9996064 32
20 9996096 32
21 9996128 32
22 9996160 32
23 9996192 32
24 9996224 32
25 9996256 32
26 9996288 32
27 9996320 32
28 9996352 32
29 9996384 32
30 9996416 32
31 9996448 32
32 9996480 32
33 9996512 32
34 9996544 32
35 9996576 32
36 9996608 32
37 9996640 32
38 9996672 32
39 9996704 32
40 9996736 32
41 9996768 32
42 9996800 32
43 9996832 32
44 9996864 32
45 9996896 32
46 9996928 32
47 9996960 32
48 9996992 32
49 9997024 32
50 9997056 32
51 9997088 32
52 9997120 32
53 9997152 32
54 9997184 32
55 9997216 32
56 9997248 32
57 9997280 32
58 9997312 32
59 9997344 32
60 9997376 32
61 9997408 32
62 9997440 32
63 9997472 32
64 9997504 32
65 9997536 32
66 9997568 32
67 9997600 32
68 9997632 32
69 9997664 32
70 9997696 32
71 9997728 32
72 9997760 32
73 9997792 32
74 9997824 32
75 9997856 32
76 9997888 32
77 9997920 32
78 9997952 32
79 9997984 32
80 9998016 32
81 9998048 32
82 9998080 32
83 9998112 32
84 9998144 32
85 9998176 32
86 9998208 32
87 9998240 32
88 9998272 32
89 9998304 32
90 9998336 32
91 9998368 32
92 9998400 32
93 9998432 32
94 9998464 32
95 9998496 32
96 9998528 32
97 9998560 32
98 9998592 32
99 9998624 32
100 9998656 32
101 9998688 32
102 9998720 32
103 9998752 32
104 9998784 32
105 9998816 32
106 9998848 32
107 9998880 32
108 9998912 32
109 9998944 32
110 9998976 32
111 9999008 32
112 9999040 32
113 9999072 32
114 9999104 32
115 9999136 32
116 9999168 32
117 9999200 32
118 9999232 32
119 9999264 32
120 9999296 32
121 9999328 32
122 9999360 32
123 9999392 32
124 9999424 32
125 9999456 32
126 9999488 32
127 9999520 32
128 9999552 32
129 9999584 32
130 9999616 32
131 9999648 32
132 9999680 32
133 9999712 32
134 9999744 32
135 9999776 32
136 9999808 32
137 9999840 32
138 9999872 32
139 9999904 32
140 9999936 32
141 9999968 32
142 10000000 32
143 10000032 32
144 10000064 32
145 10000096 32
146 10000128 32
147 10000160 32
148 10000192 32
149 10000224 32
150 10000256 32
151 10000288 32
152 10000320 32
153 10000352 32
154 10000384 32
155 10000416 32
156 10000448 32
157 10000480 32
158 10000512 32
159 10000544 32
160 10000576 32
161 10000608 32
162 10000640 32
163 10000672 32
164 10000704 32
165 10000736 32
166 10000768 32
167 10000800 32
168 10000832 32
169 10000864 32
170 10000896 32
171 10000928 32
172 10000960 32
173 10000992 32
174 10001024 32
175 10001056 32
176 10001088 32
177 10001120 32
178 10001152 32
179 10001184 32
180 10001216 32
181 10001248 32
182 10001280 32
183 10001312 32
184 10001344 32
185 10001376 32
186 10001408 32
187 10001440 32
188 10001472 32
189 10001504 32
190 10001536 32
191 10001568 32
192 10001600 32
193 10001632 32
194 10001664 32
195 10001696 32
196 10001728 32
197 10001760 32
198 10001792 32
199 10001824 32
200 10001856 32
201 10001888 32
202 10001920 32
203 10001952 32
204 10001984 32
205 10002016 32
206 10002048 32
207 10002080 32
208 10002112 32
209 10002144 32
210 10002176 32
211 10002208 32
212 10002240 32
213 10002272 32
214 10002304 32
215 10002336 32
216 10002368 32
217 10002400 32
218 10002432 32
219 10002464 32
220 10002496 32
221 10002528 32
222 10002560 32
223 10002592 32
224 10002624 32
225 10002656 32
226 10002688 32
227 10002720 32
228 10002752 32
229 10002784 32
230 10002816 32
231 10002848 32
232 10002880 32
233 10002912 32
234 10002944 32
235 10002976 32
236 10003008 32
237 10003040 32
238 10003072 32
239 10003104 32
240 10003136 32
241 10003168 32
242 10003200 32
243 10003232 32
244 10003264 32
245 10003296 32
246 10003328 32
247 10003360 32
248 10003392 32
249 10003424 32
250 10003456 32
251 10003488 32
252 10003520 32
253 10003552 32
254 10003584 32
255 10003616 32
256 10003648 140121289508048
257 140121299510096 1632
258 140121299509872 1824
259 140121299510320 1408
260 140121299510224 1472
261 140121299509744 1984
262 140121299510448 1248
263 140121299510480 1248
264 140121299510512 1184
265 140121299510544 1184
266 140121299510576 1120
267 140121299510608 1120
268 140121299510640 1056
269 140121299510672 1056
270 140121299510704 992
271 140121299510736 992
272 140121299510768 928
273 140121299510800 928
274 140121299510832 864
275 140121299510864 864
276 140121299510896 800
277 140121299510928 800
278 140121299510960 736
279 140121299510992 736
280 140121299511024 672
281 140121299511056 672
282 140121299511088 608
283 140121299511120 608
284 140121299511152 544
285 140121299511184 544
286 140121299511216 480
287 140121299511248 480
288 140121299511280 416
289 140121299511312 416
290 140121299511344 352
291 140121299511376 352
292 140121299511408 288
293 140121299511440 288
294 140121299511472 224
295 140121299511504 224
296 140121299511536 160
297 140121299511568 160
298 140121299511600 96
299 140121299511632 96

As you can see, -5..255 are placed in sequence in memory (with addresses differing by 32 from each other.) This is done when Python starts. Other integers are placed as they are needed in free spaces.

Placing mutable objects in memory

Unlike strings and integers, lists are mutable -- their contents can be changed. Consider:

In [4]:
L1 = [1, 2, 3]
L2 = [1, 2, 3]

We cannot have both L1 and L2 stored in the same address, because that would mean that modifying the contents of L1 (e.g. using L1[0] = 5, but not using L1 = [5, 2, 3], which is different) would also modify the contents of L2.

Indeed, we see

In [5]:
print(id(L1))
print(id(L2))
140121328452552
140121328584008

To remind you, here is what would happen if the addresses of L1 and L2 had been the same:

In [6]:
L1 = [1, 2, 3]
L2 = L1 #id(L1)==id(L2) now, since L1 and L2 are aliases
L2[0] = 5
print(L1)
print(L2)
[5, 2, 3]
[5, 2, 3]

Both L1 and L2 were changed when we went L2[0] = 5!