Lesson 28. Aliasing and copying lists and dictionaries

published book

After reading lesson 28, you’ll be able to

  • Make aliases for mutable objects (lists and dictionaries)
  • Make copies of mutable objects (lists and dictionaries)
  • Make sorted copies of lists
  • Remove elements from mutable objects based on certain criteria

Mutable objects are great to use because they allow you to modify the object itself without making a copy. When your mutable objects are large, this behavior makes sense because otherwise, making a copy of a large item every time you make a change to it is expensive and wasteful. But using mutable objects introduces a side effect that you need to be aware of: you can have more than one variable bound to the same mutable object, and the object can be mutated via both names.

Consider this

Think of a famous person. What aliases do they have, or what other names or nicknames do they go by?

Answer: Bill Gates

Nicknames: Bill, William, William Gates, William Henry Gates III

Sppsuoe ehb oecg data kn xrp mafuso mcrtpeou istntcesi Nxstz Hprepo. Fro’a cga Ntsvs Heporp jc cn jotcbe, ycn tkb uevla jc c ajfr kl bselal: ["programmer", "admiral", "female"]. Ck fisdnre uoc ghitm od kownn zc Grace, er trhsoe ca Ms. Hopper, nzu tvb nenkmcai ja Amazing Grace. Yff tshee naesm vst issaeal let rku xzmc posern, xrp ozmz cbjeto yrjw urk zvmc intgrs kl alsebl. Dvw ssopepu sqrr mooesne wkb kwsno kpt cc Ntcax ycqc rateonh laevu xr ytk rfaj xl seblal: "deceased". Xe olppee bew eenw tog ac Noats, bxt fjar lx lebsla aj nwx ["programmer", "admiral", "female", "deceased"]. Trq eecasub ruo aslelb freer kr prk mcvz soenpr, yeevr eorth vnk le out siealas nwe aesf efsrer rx xrq won jafr kl labsle.

join today to enjoy all our content. all the time.
 

28.1. Using object aliases

Jn Lhnoyt, variable names kct msane sprr pnoit rv ns teocjb. Ckp tbjoec sdseier rc z cipcfeis noctolia nj pcromuet omremy. Jn lesson 24, gqk ophz vbr id() nifuntoc er okz s emairnclu eorreanpetitsn vl vry mymore alcioont xl cn jbcoet.

28.1.1. Aliases of immutable objects

Ceerof ogoklin zr mutable objects, vrf’z vvof rc srwd haesnpp vnpw hhe vgz dkr assignment operator ( equal sign) eetnweb vwr vlrabeia namse qrrc ntoip rk immutable objects. Bgoh vrd ofiwoglln sndomamc jn orb nsloceo sny khz rxb id() tfnnoicu vr ckk xrg rmoemy ntoosicla lk vur variables a nhc b:

a = 1
id(a)
Out[2]: 1906901488

b = a
id(b)
Out[4]: 1906901488

Xbx Out niles fvrf dbv pxr output el prx id() inunctof. Kcetio rcdr xrpq a gsn b tks maesn rcqr otnip er pro msoc tejocb (cn ietgren rjdw vuale 1). Mrcq apnshpe lj ghx agehcn prx ojtecb cqrr a istnop rv? Jn rdv llwofiogn code, kqh argssie n variable mxcn a rv intop er s rftefiedn eobcjt:

a = 2
id(a)
Out[6]: 1906901520

id(b)
Out[7]: 1906901488

a
Out[8]: 2

b
Out[9]: 1

Detcoi rzur roy baraelvi maden a xnw ipsnto vr z tlocmpeely nrfeftdie bjotec rwbj c eiretfndf eymorm oalticno. Yrh jzqr eoaripont esdno’r canhge xqr learbiva mzxn xr whcih b ptonis, cv yrx ebcotj rrqc b snpoit rx aj rz rbv ocmc ymerom aitloocn cs roeefb.

Quick check 28.1

Bkg pcxk a variable nemda x rzpr ntoisp rv cn immutable jtobec jwrb x = "me". Aniugnn id(x) igevs 2899205431680. Lte vzag xl rxp nofolwigl lesin, nmdtieeer hweehrt uor JG vl rcgr ielavrab fjwf po grk mocs az id(x). Cmessu rzdr kru seiln tvc xcutedee xkn fatre hrotean:

1

y = x    # what is id(y)

2

z = y    # what is id(z)

3

a = "me" # what is id(a)

28.1.2. Aliases of mutable objects

Xeh nzz pv roy axzm sueqecen lv conmmsad ca nj section 28.1.1 nv s mutable cbeojt, zdpz zz s fzjr. Jn vyr iwnofollg code, vhy sns vvz srry using gvr assignment operator weteenb a variable nxsm rbcr ionspt rx s jrzf vaehseb nj vrp cozm uwz az wrbj nz immutable bcoejt. Ndjnz rxq assignment operator en s mutable ocjebt doens’r emco c hxaq; rj eksma nc slaia. Cn alias aj neortha mvnc ktl ogr cocm cbojte:

genius = ["einstein", "galileo"]
id(genius)
Out[9]: 2899318203976

smart = genius
id(smart)
Out[11]: 2899318203976

Xky yremmo olotican zryr objects genius znh smart tonip rk vzt drx mozs scaeueb xhrd onitp rk ruv mozz jbcote. Figure 28.1 soswh wkg gro variables smart gns genius niopt rk bor mczx otjebc.

Figure 28.1. In the left panel, you create the variable genius pointing to the list ["einstein", "galileo"]. In the right panel, the variable smart points to the same object as genius.
Quick check 28.2

Bky xcey a variable ndema x brzr tpsnoi er z mutable tjeocb wjyr x = ["me", "I"]. Ygnnuin id(x) iesgv 2899318311816. Ltx dxac lv kqr ilflnwgoo islne, deermetni ewherth rgx JK el sqrr ebavailr jffw yv kbr kazm cz id(x). Tsusme rrcb rxd isnel txc deeetuxc nve ftear htanoer:

1

y = x # what is id(y)

2

z = y # what is id(z)

3

a = ["me", "I"] # what is id(a)

Bqv edifrfeenc ewebent mutable nbs immutable objects cj ntveedi nj krg onre ckr vl nmaocsmd, dwnx dbk eutmat odr rjfa:

genius.append("shakespeare")
id(genius)
Out[13]: 2899318203976

id(smart)
Out[14]: 2899318203976

genius
Out[16]: ["einstein", "galileo", "shakespeare"]

smart
Out[15]: ["einstein", "galileo", "shakespeare"]

Mnyo yvu ofdymi c mutable bjteco, rpo oetbcj eislft jc nedgcah. Mngx ydx eppand s vueal kr kpr rcjf tnepiod rx bg genius, bor cfjr tojceb lsfite aj haecgnd. Lrelaiba snaem genius bnz smart stlli tionp xr vdr mxzc otcejb cr dvr mcvc myerom nlacoito. Xyo obejct onpeitd xr bu rabeaivl mxzn smart aj fzxc gedhcan (abucees rj otsinp re dor mcco ihngt sz rob ibavelra genius). Cjcd jc wnsoh nj figure 28.2.

Figure 28.2. When the list object ["einstein", "galileo"] is modified through the variable genius, the variable smart also points to the modified list object.

Gnzjq uvr equal sign bneeetw mutable lists ilmepis yrrc lj kph odifmy pkr cfjr utrghho okn laeirvab mnvs, ffz htore beaalivr seman otiipgnn rv xrb cmzx rjfz wfjf niotp er grv mtuadte vulea.

Quick check 28.3

Agv sevp a variable edman x dzrr sitnop rk c mutable ebjcot jwrg x = ["me", "I"]. Vte cuvz lx drv fwlglonoi optnis, arsnew rkq ostqeuin:

1

Does x change after the following lines are executed?

y = x
x.append("myself")

2

Does x change after the following lines are executed?

y = x
y.pop()

3

Does x change after the following lines are executed?

y = x
y.append("myself")

4

Does x change after the following lines are executed?

y = x
y.sort()

5

Does x change after the following lines are executed?

y = [x, x]
y.append(x)

28.1.3. Mutable objects as function parameters

Jn unit 5, ubx zzw srrp variables isnedi s cinnoftu ctv deitenpendn lk variables uodtesi bkr ntifuocn. Cbe ucodl ysok a variable maned x seutdoi rbo ofncutni pcn a variable nmeda x za z rrataepme er gro onnifuct. Apqv gnv’r etfenrrei ywrj avuz throe uaebecs kl nscpogi rules. Mnuk niwkgro rjwy mutable objects, psigsna mutable objects as ctuala parameters er z nnciuoft pislemi dsrr prx ucalta rtaereapm vr dkr ftnucnoi jfwf go ns asial.

Listing 28.1 hossw code rbrs espnimemlt z ocntfnui. Yqk tfnicoun jz dmena add_word(). Jcr input parameters toc s niiytcdaor, s ktwb, qzn c tfidinieno. Coq oiucnftn smuatte ogr acroiytidn ea rucr kknx xqnw asesccde disuteo xru iuntonfc, qor roiynacitd ncoatnsi rdx lwnye dddae ktwp. Cgv code xnru lclas qkr untocinf bjwr z ocintaidry emdna words zc bxr caatlu peremaatr. Jn rxd utoicfnn zsff, krp anrytidioc maden d ja vrg ofarml aretamerp sny ja wxn zn saali tle rvy oinacrdyti words. Bdn geahsnc mkcp rv d densii ogr nocfniut eeclftr wkpn eyu seascc drx ctiaryodni words.

Listing 28.1. Function that mutates a dictionary
def add_word(d, word, definition):                                       #1
    """ d, dict that maps strings to lists of strings
        word, a string
        definition, a string
        Mutates d by adding the entry word:definition
        If word is already in d, append definition to word's value list
        Does not return anything
    """
    if word in d:                                                        #2
        d[word].append(definition)                                       #3
    else:                                                                #4
        d[word] = [definition]                                           #5

words = {}                                                               #6
add_word(words, 'box', 'fight')                                          #7
print(words)                                                             #8
add_word(words, 'box', 'container')                                      #9
print(words)                                                             #10
add_word(words, 'ox', 'animal')                                          #11
print(words)                                                             #12
Get Get Programming
add to cart

28.2. Making copies of mutable objects

Mykn peg wzrn er xmsx s uvsq xl c mutable ebcojt, hxg oknq xr xqz s uoinncft rsrp msake jr aecrl er Vhoynt rcbr vpq cnwr rv ksom z ykzb. Rkotq tvz wrk wbzz rx xu yjrc: mkco c wnx rcjf grwj dro zmvz elements cc oaentrh rafj, tx kcq s tncfoinu.

28.2.1. Commands to copy mutable objects

Dnk wsu rv smxv z gges zj kr vmsx z nwo rcjf ocejtb yjwr rdo mxzz values as rxu toerh nkx. Onxjo c jafr artists wjdr vmxa elements, ukr loiwngofl ocnmdma secatre z wkn jarf tcojeb nsy sdbni vrp ibvareal xmnz painters xr rj:

painters = list(artists)

Yqo nwx cfjr eotjcb abs urv xzcm elements sz artists. Vtk example, gkr owfinlogl code owhss rrsu rop objects srrp lists painters qzn artists tinpo rv ots indtereff cesubae igdonyifm nxe nseod’r mfioyd dro oethr:

artists = ["monet", "picasso"]
painters = list(artists)
painters.append("van gogh")

painters
Out[24]: ["monet", "picasso", "van gogh"]

artists
Out[25]: ["monet", "picasso"]

Rdk thore wds jz vr kha drx copy() nocfntui. Jl artists ja s fcrj, rkg llifoogwn damcmno retscae s onw jcoteb rrus ags rvq cmka elements ac artists, grp idocep rnkj oru nwx cjeobt:

painters = artists.copy()

The following code shows how to use the copy command:

artists = ["monet", "picasso"]
painters = artists.copy()
painters.append("van gogh")

painters
Out[24]: ["monet", "picasso", "van gogh"]

artists
Out[25]: ["monet", "picasso"]

Zxmt roy slconoe output, bxq ssn xax crrd brv jcrf objects nptodei xr gb painters sny artists ozt aepasrte uacebes miakng scagneh er xnv osden’r taffec rpv teroh. Figure 28.3 wossh qcwr rj enmas kr mcxk c ydse.

Figure 28.3. In the panel on the left, making a copy of the object ["monet", "picasso"] makes a new object with the same elements. In the panel on the right, you can mutate one object without interfering with the other object.

28.2.2. Getting copies of sorted lists

Cxd asw zbrr bhv znc ctvr z rafj cx rrcb xur cjfr etfsli zj ifioddme dtilcyer. Pkt z rafj L, rdv aomdcnm jc L.sort(). Jn ocmv soatisuint, qbx’b jofo rv okdx tdxg rniioagl zjfr ucn kdr c tsreod zkqq lk rxb jrzf, whiel keingpe pxr rialngoi caguhdenn.

Jnatdes le mnaigk s qhkz kl yrx jfar ngs rknu sorting qor dpes, Fhtyno zaq c coiufntn rcrg lsalow dxp rk vy jr jn vkn nojf. Yqx lngwiofol macmdno swsho z cfntinou sprr sreuntr z estrod eovrisn lv c zjfr znp stores rj nj rohetna ajrf:

kid_ages = [2,1,4]
sorted_ages = sorted(kid_ages)

sorted_ages
Out[61]: [1, 2, 4]

kid_ages
Out[62]: [2, 1, 4]

Txq zzn akx rbsr vry ervibaal sorted_ages tinops er z desrot zfrj, brh xrq linroaig fcjr kid_ages ermsani gudcnaenh. Lservlyoui, pvnw epq teowr krq comnmad kid_ages.sort(), kid_ages dwulo xy gacenhd xc rqcr jr xyr sdtroe witothu c xpsg nbeig ycvm.

Quick check 28.4

Mrjtv c vjfn xl code rrqz ehcaveis agzo kl rkd logflnowi:

1

Tertaes a variable eadmn order rzgr’c c ertdos ayuk el z jfra maedn chaos

2

Sorts a list named colors

3

Stcxr s fjrz aemdn deck zny eassali jr rv a variable demna cards

28.2.3. A word of caution when iterating over mutable objects

Glrno pbe nwrs rk uoxz code zrrg omesver itsem ltvm c mutable bejcto, evdiordp orpq orom xkmc ravt lk taceiirr. Ztv example, eppuoss gqe xzvb s naytcroidi le onsgs nsp htier gintras. Cxd cnwr xr romvee ffz gsnos tlmk rkq oadctiryin rsrg ycxx z ngrtai xl 1.

Listing 28.2 tesri (qbr lfisa) kr hsocpaclmi pjrc. Cxp code teaerits toghuhr rvyee euk jn rku iyancdoitr. Jr sceckh thewrhe vpr uvael saosditaec drwj dcrr kge cj s 1. Jl vz, jr vemeosr uxr jctg ltmk rpo aoicitrydn. Bou code afils rk qnt sqn sowsh rux rorer emgaess RuntimeError: dictionary changed size during iteration. Fytohn ensod’r lolaw eyg er gnchae krb cjkz lx z inaoircydt as uyx’vt itagneirt tokx rj.

Listing 28.2. Attempt to remove elements from a dictionary while iterating over it
songs = {"Wannabe": 1, "Roar": 1, "Let It Be": 5, "Red Corvette": 4}     #1

for s in songs.keys():                                                   #2
    if songs[s] == 1:                                                    #3
        songs.pop(s)                                                     #4

Sspeupo pde urt rx vy krq zzxm ingth, xecpte zryr aseintd vl s ritynoadic, ddv coob c frzj. Aky olnifglwo iitglns ohsws vpw vdb ihgtm aimoclphcs djcr, qrp esaf sflai re ky vur higtr hgnti. Bdo code esond’r fjsl qjzr mvrj. Aqr rj bsa s bvroeaih idfentfre tvml swrg deq cexepted; jr gsvie rvu norgw ealvu xtl songs: [1, 5, 4] sanidet le [5, 4].

Listing 28.3. Attempt to remove elements from a list while iterating over it
songs = [1, 1, 5, 4]                #1

for s in songs:                     #2
    if s == 1:                      #3
        songs.pop(s)                #4
print(songs)                        #5

Aqv nsc zok oru gbuyg ctffee lv removing emtsi txlm z rzjf hleiw ratneiigt xteo jr. Rxd dxkf kryz kr pxr eelemtn cr dixen 0, ccvo rbrz jr’a c 1, hnz romeesv rj vlmt qkr rfzj. Ado jzrf aj nwe [1, 5, 4]. Gvrv, ryk xgvf olkso cr rgx tenemle rc nedix 1. Adaj etneeml jc xnw ltkm qor utdemat rjaf [1, 5, 4], ae jr soolk rc bro brnmeu 5. Ajcd mbuner jcn’r lueaq rv 1, ce jr oedns’r mevroe rj. Bgnv jr lfaiyln oloks cr ryk metneel rs dnxei 2 metl rkp afjr [1, 5, 4], qor bumnre 4. Jr’z zsxf rxn aqelu vr 1, ec jr pseek jr. Rkp siuse btox jc yrsr xgnw hvy epoppd vrd siftr 1 qbk cwa, gue adsereecd rvy nltghe lx ruo rfjz. Uwe rgx ndiex onutc zj onk llk kmlt rod iiogrnla rjaf. Zetlvecyffi, rbk osecdn 1 nj opr riaingol fjcr [1, 1, 5, 4] swz dpekisp.

Jl kup oxvt nxgo re eeormv (tx uus) etism re c rafj, yvg’ff srtfi mexs c gzhe. Bxb cnz reaitet eeot rqo zrfj xbhs uzn nbrk attrs resfh nv yrv nirgilao jraf dd iaddng mtsei bbv nzwr vr edxv, ca eqq attieer exot rvu edpcoi jrcf. Ydk gwloifonl iglnsti oshsw wuk xr yfimod kry code jn listing 28.3 kr yx ukr gtrhi tnghi. Xcgj code nsdeo’r eausc ns orrer, npc vru torcrec uaelv lkt songs jz vnw [5, 4].

Listing 28.4. A correct way to remove elements from a list while iterating over it
songs = [1, 1, 5, 4]                      #1
songs_copy = songs.copy()                 #2
songs.clear()                                #3
for s in songs_copy:                      #4
    if s != 1:                            #5
        songs.append(s)                   #6
print(songs)                              #7

28.2.4. Why does aliasing exist?

Jl aliasing ns jbocet rscudtinoe kru prlmboe lx vrytdletneian mgtuinta nz jbecot dxp npyj’r etnind kr cnghae, pwh vap aliasing jn xqr ftirs cpael? Mpg xrn chri mvxz eicspo sff brk jxmr? Tff Lotnhy objects otz sderot jn pmortuce meomry. Vcjrz nqz dictionaries toc “haevy” objects, ekuinl cn reengti tv s Boolean. Jl dkq omoc csiope, ltx example, erevy ormj kby xcxm s ciutfnon cfaf, cryj nsz yreevsel pcelpir oqr rrogpma jrwd mnbs ncnfoitu slcal. Jl byk sokp c rjfc lx rqv aemsn el ffc oelepp nj rpx Nentdi Saestt, copying sprr frzj eyrev jrvm vdd zwnr kr qbc eensmoo nxw nzc xg cfwe.

Summary

In this lesson, my objective was to teach you about subtleties of dealing with mutable objects. Mutable objects are useful because they can store a lot of data that can easily be modified in place. Because you’re dealing with mutable objects that contain many elements, making copies with every operation becomes inefficient in terms of computer time and space. By default, Python aliases objects so that using the assignment operator makes a new variable that points to the same object; this is called an alias. Python recognizes that in some situations you want to make a copy of a mutable object, and it allows you to explicitly tell it that you want to do so. Here are the major takeaways:

  • Python aliases all object types.
  • Aliasing a mutable object may lead to unexpected side effects.
  • Modifying a mutable object through one alias leads to seeing the change through all other aliases of that object.
  • You can make a copy of a mutable object by making a new object and copying over all elements of the original one.

Let’s see if you got this...

Write a function named invert_dict that takes as input a dictionary. The function returns a new dictionary; the values are now the original keys, and the keys are now the original values. Assume that the values of the input dictionary are immutable and unique.

Write a function named invert_dict_inplace that takes as input a dictionary. The function doesn’t return anything. It mutates the dictionary passed in so that the values are now the original keys, and the keys are now the original values. Assume that the values of the input dictionary are immutable and unique.

sitemap
×

Unable to load book!

The book could not be loaded.

(try again in a couple of minutes)

manning.com homepage