Uh, pitkästä aikaa aloittaa itse keskustelun. Tuntuupa epätoivoiselta.
Minulla ei ole mitään ongelmaa, mutta haluaisin tietää, onko parempaa keinoa käsitellä pythonissa listoja kuin oma viritelmäni.
Sovitaan, että on lista a = []
, jolle myöhemmin määrätään pari "alkiota", jos niitä sellaisiksi pythonissa kutsutaan. Eli käy näin:
a = [(5, 5), (3, 2)]
Nyt ohjelmoija haluaa vähentää ensimmäisen alkion toisesta sisäalkiosta kaksi (sanokaa, jos keksimäni termit aiheuttavat facepalmia). Tyypillisesti C-ohjelmoijana ajattelin: "Eli siis a[0][1] -= 2
". Tööt:
C:\nyrre\ohjelmointi\harjoitukset>testi.py Traceback (most recent call last): File "C:\nyrre\ohjelmointi\harjoitukset\testi.py", line 2, in <module> a[0][1] -= 2 TypeError: 'tuple' object does not support item assignment
Ahaa. Sitten lähdin kikkailemaan ja päädyin tällaiseen ratkaisuun, joka on viimeisimpäni:
a = [(5, 5), (3, 2)] #vähennys a[0] = (a[0][0], a[0][1] - 2) print a[0]
Viimeisin rivi tulostaa (5, 3). Tadaa.
Tuntuu jotenkin hassulta kikkailulta. Varmasti on parempi tapa, kertokaa.
Käyttämäsi "alkiot" (eli sulkujen sisällä oleva lukupari) ovat nimeltään tupleja, ja niitä ei ole tarkoitettu muokattavaksi. Ainoa tapa muokata tupleja on luoda uusi tuple, kuten olet tehnyt esimerkissäsi. Sinuna käyttäisin sisäkkäisiä listoja, sillä listan yksittäisiä alkioita pystyy muokkaamaan helposti:
a = [[5, 5], [3, 2]] a[0][1] -= 2
Tämän jälkeen a = [[5, 3], [3, 2]].
Jos on monimutkaista ja muokattavaa tietoa, suositeltavaa on tehdä class, jossa on halututu operaatiot, eikä käyttää nimetöntä tuplea. Neuvon nyt alla miten tuplen kanssa voi tehdä.
Monesti selkeä tapa on tehdä apufunktio ja käyttää sitä jokaiseen listan alkioon. Tähän on kaksi tapaa Pythonin perusrakenteissa, joista listakooste on se suositeltavampi yleensä.
Kirjoitan nyt koodit suoraan, joten ne ehkä eivät käänny (tulkkaannu?). Mutta pieniä korjauksia vain vaativat, jos kämmäsin.
def muuta (tuple): "Vänkkää tuplea." a, b = tuple # puretaan tuple kahdeksi muuttujaksi return (a+2, b-2) # kootaan uusi, nyt vaikka näin lista = [(1,2), (3,4), (5,6)] # map on yksi tapa uusi_lista = map (muuta, lista) # listakooste on sama asia eri näköisenä uusi_lista2 = [muuta(x) for x in lista] # mitä ne ovat syöneet? print lista print uusi_lista print uusi_lista2
Huomaa, että tässä koko lista kopioidaan. Jos se veisi liikaa muistia, ei näin kannata tehdä.
Generaattorit säästävät muistia, joten niitäkin voit vilkuilla joskus tämänlaiseen käyttöön. Ihan hyväksyttävää on myös tehdä sellainen rehellinen for-silmukka, kuten C-kielessä konsaan.
Pitää käydä läpi xrange (0, len(lista)) indekseinä. Sen silmukan sisällä voi sanoa, jotta lista[indeksi] = muuta (lista[indeksi]) .
Stini kirjoitti:
Käyttämäsi "alkiot" (eli sulkujen sisällä oleva lukupari) ovat nimeltään tupleja, ja niitä ei ole tarkoitettu muokattavaksi.
No niin, mietinkin aikaisemmin, mitä väliä haka- ja kaarisuluilla on! Kuvittelin niiden olevan vain koodin ulkonäköä parantava seikka ja siirryin itse käyttämään hakasulkuja uloimmaisina. :)
Kiitos selvennyksestä molemmille.
Syy siihen, miksi Python erottelee muutettavat (mutable) ja pysyvät (immutable) tietorakenteet on siinä, että niitä yleensä käsitellään viittausten kautta, ja niitä voidaan käyttää avaimina dict-taulukossa. Dict on eräänlainen assosiatiivinen taulukko. Perliksi se on hash ja C++:ssaksi map :-)
Jos nyt joku käy käpistelemässä viittauksen takana olevaa tietoa jotenkin, herää kysymys mitä sieltä dictistä pitäisi tulla ulos, kun samalla viittauksella myöhemmin katsotaan. Tästä mahdollisesti johtuvia sekaannuksia on yritetty välttää ja tehty tällainen sääntö.
Pythonin muuttujia voi muuten ajatella aika lailla samanlaisiksi kuin C++:n smart pointereita, paitsi ettei niillä ole tyyppiä. Merkkijonoon viittavaan muuttujan voi laittaa viittamaan lukuun tai listaan tuosta vaan.
No esimerkki vielä. Jos haluat laittaa jotain tietoa vaikkapa koordinaattien mukaan dictiin, tämä toimii:
pisteet = {} # aluksi luomme tyhjän dictin pisteet[(3,5)] = "tosi jännä piste" pisteet[(8,-3)] = "tähän loppuu punainen jana, mistä lie alkaa?"
Voit itse kokeilla, mitä tapahtuu jos tuossa laittaa hakasulut sisemmiksi ja yrittää laittaa listan avulla tietoa talteen. Virhettähän se pukkaa.
Immutable-tyyppejä ovat mm. luvut, tuplet, stringit ja frozenset. Se viimeinen on kuin tavallinen set, mutta sitä ei voi muokata. Ylläri.
Listasta saa tuplen näin: tuple (lista)
Aihe on jo aika vanha, joten et voi enää vastata siihen.