Arcade-pelien ohjelmointi
Pythonilla ja Pygamella

Chapter 7: Perehdytään listoihin

7.1 Datatyypit

Video: Introduction to Lists

Tähän mennessä tässä materiaalissa olemme tutustuneet neljään datatyyppiin:

Pythonissa funktiolla type saadaan näkyviin datan tyyppi.

type funktio ei ole muutoin hyödyllinen tämän materiaalin käytössä, mutta datatyyppien tutkimiseen tässä yhteydessä se on varsin käytännöllinen. Kirjoita seuraavat IDLE editorin shelliin (komentokehotteeseen). (älä avaa uuteen ikkunaan ja tee tästä ohjelmaa, koska se ei toimi.)

type(3)
type(3.145)
type("Hi there")
type(True)
Output:
>>> type(3)
<class 'int'>

>>> type(3.145)
<class 'float'>

>>> type("Hi there")
<class 'str'>

>>> type(True)
<class 'bool'>

Voit tutkia myös muuttujan tyypin type funktiolla seuraavasti.

x = 3
type(x)
Useita kolikoita poimittavana? Käytä tässä listaa!

Tässä kappaleessa opimme kaksi uutta tietotyyppiä: Listat (Lists) ja Monikko (Tuples). Kirjoita Pythoniin shelliin seuraavat rivit ja katso, mitä tietotyyppejä Python näistä löytää:

type(  (2, 3, 4, 5) )
type(  [2, 3, 4, 5] )

7.2 Lista käytännössä

Miten toteuttaisit ostoslistan tietokoneessa ohjelmoimalla?

fig.grocery_list
Figure 7.1: Tietokoneessakin käytetään listoja

Kokeile seuraavat esimerkit IDLEn komentokehotteessa. Luodaksesi listan ja tulostaaksesi sen kirjoita:

>>> x = [1,2]
>>> print(x)
[1, 2]

Tulosta yksittäinen lista-alkio:

>>> print(x[0])
1

Print-lauseen hakasulkeissa olevaa lukua kutsutaan indeksiksi. Huomaa, että lista-alkioiden indeksointi alkaa 0:sta.Joten listassa, jossa on 10 alkiota, ei ole mahdollista osoittaa indeksiä [10]. Tämä johtuu siitä, että listassa on indeksi [0] - [9]. Tämä saattaa vaikuttaa epäloogiselta, mutta samanlaista 0:sta alkavaa indeksointia käytetään useissa eri ohjlemointikielissä.

Voit ajatella listan olevan kuin jääpalakotelo, jossa kussakin lokerossa on jokin luku (katso kuva 7.2.) Listassa jokaisen lokeron paikan kertoo indeksi, jotka siis alkavat indeksistä 0. Indeksi kasvaa järjestyksessä alkaen 0:sta, kun taas indeksin osoittamassa 'lokerossa' voi olla mitä tahansa; esim. mikä tahansa luku.

älä sekoita keskenään listan indeksiä ja alkion arvoa!

Jatkossa sinun on ymmärrettävä, että lukulistojen käsittelyssä on erotettava kaksi asiaa: sijainti ja arvo. Sijainti, siis indeksi, ilmaisee missä listan kohdassa jokin arvo sijaitsee. Listojen kanssa on siis aina tiedettävä kumpaako haluat käsitellä indeksiä vai arvoa.

Listan tietyssä paikassa (sen 'lokeroissa') olevia arvoja on helppo käsitellä. Mutta tietyn arvon hakeminen listasta onkin sitten hankalampaa. Kappaleessa 15 selvitetään kuinka alkion arvot saadaan selville.

fig.ice_cube_tray
Figure 7.2: Lista on kuin jääpalalokero

Listan tietyssä paikassa olevan alkion arvo voidaan asettaa asetuslauseella. Alla olevassa esimerkissä listan (sama lista, joka esitettiin edellä) ensimmäiseen alkioon (paikassa 0) asetetaan luku 22. Indeksissä 0 alkion arvo on 22 ja toisen alkion arvo säilyy muuttumattomana.

>>> x[0] = 22
>>> print(x)
[22, 2]

Ohjelmassa voidaan luoda myös monikko, “tuple.” Tämä tietotyyppi toimii kuten lista kahdella erolla. Ensinnäkin, monikko luodaan kaarisulkeiden sisään (listassa hakasulkeet). Toiseksi, kerran luotua monikkoa ei voida enää muuttaa. Katso esimerkki alla:

>>> x = (1, 2)
>>> print(x)
(1, 2)
>>> print(x[0])
1
>>> x[0] = 22
Traceback (most recent call last):
  File "<pyshell#18>", line 1, in <module>
    x[0] = 22
TypeError: 'tuple' object does not support item assignment
>>>

Kuten koodin virheilmoituksesta näemme, monikon arvon uudelleen asetus ei ole mahdollinen. Mitä hyötyä meille voisi olla tällaisesti muuttumattomasta monikosta? Yksi syy on, että tietokone suorittaa koodin nopeammin, koska monikon arvot eivät muutu. Toinen syy on, että tietyissä tilanteissa on tarvetta luoda listoja (monikoita). Esimerkiksi RGB väriarvojen tallentaminen monikkoon on viisasta, koska emme halua väriarvojen muuttuvan ohjelman suorituksen aikana. (Monikkoa voidaan kutsua mutatoitumattomaksi, eli sen alkioiden arvoa ei voi muuttaa.)

Taulukko, jota englanniksi kutsutaan yleisesti nimellä array, on lista, jossa voi olla mitä tahansa alkioita. Se on erittäin tärkeä tietorakenneohjelmoinnissa. Pythonin tietotyyppi “list” on hyvin samankaltainen yleisen array tietotyypin kanssa.

7.3 Lista-alkioiden läpikäynti

Video: Iterating Through a List

Listan-alkioiden läpikäynti, esimerkiksi tulostusta varten, voidaan kahdella erilaisella for silmukalla.

Lista-alkioiden läpikäynti eli iterointi voidaan tehdä “for-each” silmukalla. Tässä rakenteessa listan alkiot käydään yksitellen läpi. Silmukassa tallennetaan alkion arvo silmukkamuuttujaan jokaisella suorituskerralla.

Syntaksi on seuraava:
for item_variable in list_name:

Tässä muutama esimerkki:

my_list = [101, 20, 10, 50, 60]
for item in my_list:
    print(item)
Output:
101
20
10
50
60

Listoihin voidaan tallentaa myös merkkijonoja:

my_list = ["Spoon", "Fork", "Knife"]
for item in my_list:
    print(item)
Output:
Spoon
Knife
Fork

Lista voi sisältää toisen listan. Tässä iteroidaan läpi listan 'lista-alkiot', mutta ei siis lista-alkiota itseään.

my_list = [ [2,3], [4,3], [6,7] ]
for item in my_list:
    print(item)
Output:
[2,3]
[4,3]
[6,7]

Toinen tapa listan läpikäymiseen on käyttää indeksimuuttujaa> ja osoittaa kutakin listan alkiota suoraan. Käytettäessä indeksimuuttujaa, laskuri 'juoksee' 0:sta listan loppuun. Jos esimerkiksi listassa on kymmenen alkiota, silmukan tulee osoittaa indekseihin 0 - 9.

Listan pituus saadaan selville len funktiolla. Ja kun tämä liitetään range funktioon, niin koko lista saadaan käytyä läpi.

my_list = [101, 20, 10, 50, 60]
for i in range(len(my_list)):
    print(my_list[i])
Output:
101
20
10
50
60

Tämä tämä on monimutkaisempi, mutta se on tehokkaampi. Tässä käsitellään suoraan listan alkioita, eikä sen kopioita ja näin listaa voidaan myös muuttaa. for-each rakenteessa ei ole mahdollista muuttaa alkuperäisen listan rakennetta.

7.4 Alkion lisääminen listaan

Uuden alkion lisääminen listaan (siis ei monikkoon) tehdään append komennolla. Esimerkiksi:

my_list = [2, 4, 5, 6]
print(my_list)
my_list.append(9)
print(my_list)
Output:
[2, 4, 5, 6]
[2, 4, 5, 6, 9]
Video: Appending to a list

Lisähuomautus: Lista -tietotyypin toteutustavan ymmärtäminen on varsin tärkeää pidemmälle opiskeltaessa. Esimerkiksi, jos lista toteutetaan esim. array eli taulukkotyyppisenä, jolloin lista on luotava riittävän suureksi jo luontivaiheessa, koska listan koko ei muutu. Onneksi Python ei luo listoista array tyyppisiä, jolloin niiden kokoa ei tarvitse 'ennustaa' luontivaiheessa.

Seuraavassa esimerkissä luodaan ensin tyhjä lista, johon käyttäjän syöttämät kokonaisluvut lisätään append -funktiolla:

my_list = [] # Empty list
for i in range(5):
    userInput = input( "Enter an integer: ")
    userInput = int( userInput )
    my_list.append(userInput)
    print(my_list)
Output:
Enter an integer: 4
[4]
Enter an integer: 5
[4, 5]
Enter an integer: 3
[4, 5, 3]
Enter an integer: 1
[4, 5, 3, 1]
Enter an integer: 8
[4, 5, 3, 1, 8]

Jos halutaan tehdä tietyn mittainen taulukko, jossa on samat alkiot, voidaan käyttää seuraavanlaista keinoa:

# Create an array with 100 zeros.
my_list = [0] * 100

7.5 Lista-alkioden summaus tai muutos

Video: Summing a List

Listan alkioiden summa voidaan 'pyörittää' seuraavilla tavoilla:

# Lasketaan listasumma
my_list = [5,76,8,5,3,3,56,5,23]

# alkuarvon tulee olla nolla
list_total = 0

# Silmukassa loopataan 0:sta listan loppuun

for i in range(len(my_list)):
	# ensin alkion 0 arvo, sitten 1, sitten 2 jne.
	list_total += my_list[i]

# Printataan tulos
print(list_total)

Sama voidaan tehdä itetoimalla lista for silmukalla läpi ilman range-funktiota:

# Lasketaan listasumma
my_list = [5, 76, 8, 5, 3, 3, 56, 5, 23]

# alkuarvon tulee olla nolla
list_total = 0

# Loopataan lista läpi kopioimalla jokaisen lista-alkion arvo muuttujaan.
for item in my_list:
	# lisätään jokainen alkio
	list_total += item

# Printataan tulos
print(list_total)

Listan lukujen arvoja voidaan muuttaa for silmukassa:

# luodaan lista
my_list = [5, 76, 8, 5, 3, 3, 56, 5, 23]

# Silmukassa loopataan 0:sta listan loppuun:
for i in range(len(my_list)):
	# kerrotaan jokainen alkio luvulla 2
	my_list[i] = my_list[i] * 2

# Printataan tulos
print(my_list)

Versio 2 ei toimi listan arvojen tuplaamisessa (kahdella kertomalla), mutta miksi ei? Koska item on kopio listan alkiosta, eikä kopion arvon muuttaminen muuta listan alkuperäistä alkiota. Näin tapahtuukin seuraavassa koodiesimerkissä.

# luodaan lista
my_list = [5, 76, 8, 5, 3, 3, 56, 5, 23]

# Loopataan läpi jokainen listan alkio
for item in my_list:
	# tämä tuplaa muuttujan item, mutta ei muuta listan alkion arvoa
	# koska item on kopio yksittäisen alkion arvosta
	item = item * 2

# Printataan tulos
print(my_list)

7.6 Merkkijonojen paloittelu

Video: Splitting Strings

Merkkijonot ovat itse asiassa merkkitaulukoita, joita voidaan käsitellä kuten listoja. Jokaisella kirjaimella on oma paikka listassa. Kokeile ajaa seuraavan koodin molemmat versiot arvolla x:

x = "This is a sample string"
#x = "0123456789"

print("x=", x)

# Listan yksittäinen merkki
print("x[0]=", x[0])
print("x[1]=", x[1])

# Osoitetaan listaa lopusta alkaen
print("x[-1]=", x[-1])

# merkit paikasta 0-5
print("x[:6]=", x[:6])
# paikka 6
print("x[6:]=", x[6:])
# paikat 6-8
print("x[6:9]=", x[6:9])

MErkkijonoja voidaan käsitellä Pythonissa muutamilla matemaattisilla operaattoreilla. Kokeile seuraavalla koodilla, miten Python suorittaa sen.

a = "Hi"
b = "There"
c = "!"
print(a + b)
print(a + b + c)
print(3 * a)
print(a * 3)
print((a * 2) + (b * 2))

MErkkijonon pituus, aivan kuten taulukoidenkin, saadaan selville len -funktiolla.

a = "Hi There"
print(len(a))

b = [3, 4, 5, 6, 76, 4, 3, 3]
print(len(b))

Merkkijonon alkiot (eli merkit) voidaan iteroida läpi merkki kerrallaan, aivan kuten listoissakin:

for character in "This is a test.":
    print(character)

Harjoituksia: Aloita seuraavalla koodilla:

months = "TamHelMaaHuhTouKesHeiEloSyyLokMarJou"

n = int(input("Anna kuukauden numero: "))

Tulosta sen kuukauden kolmikirjaiminen lyhenne, jonka numeron käyttäjä syöttää. (Laske merkkijonosta aloituskohdasta ja käytä äsken opittua alimerkkijonon esimerkkiä, (katso erityisesti kohta ' #merkit paikasta 0-5') jolla saat kyseisen kuukauden (alimerkkijonon) tulostettavaksi. )

7.7 Salauskoodeja

Tällä koodilla saat tulostettua merkkijonon merkit yksi kerrallaan:

plain_text = "Tämä on testi. ABC abc"

for c in plain_text:
    print(c, end=" ")
Video: Secret Codes

Tietokone ei varsinaisesti tallenna merkkijonojen kirjaimia, vaan sen sijaan tallennetaankin numerokoodeja. Kukin numerokoodi vastaa jotakin kirjainmerkkiä. Tietokone kääntää (enkoodaa) nämä numerokoodit kirjaimiksi niin sanotun Unicode järjestelmän mukaisesti. Täydellinen nimitys tälle enkoodaukselle on Universal Character Set Transformation Format 8-bit, usein lyhenteellä UTF-8 esitettynä.

Unicode taulukko sisältää länsimaiset aakkosmerkit, välimerkit ja erikoismerkkejä, jotka esitetään lukualueen 0-127 koodeilla. Kukin kirjain esitetään yhdellä tavulla (8-bittiä). Muut merkit, kuten kyrilliset ja skandinaavit, esitetään useamman tavun avulla. Seuraavassa taulukossa on esitettynä muutama Unicode merkistön koodit ja sitä vastaava merkki:

ValueCharacterValueCharacterValueCharacterValueCharacter
40(61=82R103g
41)62>83S104h
42*63?84T105i
43+64@85U106j
44,65A86V107k
45-66B87W108l
46.67C88X109m
47/68D89Y110n
48069E90Z111o
49170F91[112p
50271G92\113q
51372H93]114r
52473I94^115s
53574J95_116t
54675K96`117u
55776L97a118v
56877M98b119w
57978N99c120x
58:79O100d121y
59;80P101e122z
60<81Q102f

Lisätietoja ASCII koodista (jonka koodit ovat lähes samat kuin Unicode koodit länsimaisilla kirjaimilla):
http://en.wikipedia.org/wiki/ASCII

Seuraava video selvittää Unicode hienouden:
http://hackaday.com/2013/09/27/utf-8-the-most-elegant-hack

Seuraavasa koodissa konvertoidaan merkkijonon merkit ASCII arvoiksi käyttämällä UTF-8 koodausta:

plain_text = "This is a test. ABC abc"

for c in plain_text:
    print(ord(c), end=" ")

This next program takes each UTF-8 value and adds one to it. Then it prints the new UTF-8 value, then converts the value back to a letter.

plain_text = "This is a test. ABC abc"

for c in plain_text:
    x = ord(c)
    x = x + 1
    c2 = chr(x)
    print(c2, end="")

Seuraava koodiesimerkki käsittelee merkkijonon UTF-8 arvoja lisäämällä kuhunkin luvun 1. Tämän jälkeen koodi konvertoidaan takaisin merkiksi.

fig.encryption
# Sample Python/Pygame Programs
# Simpson College Computer Science
# http://programarcadegames.com/
# http://simpson.edu/computer-science/

# Explanation video: http://youtu.be/sxFIxD8Gd3A

plain_text = "This is a test. ABC abc"

encrypted_text = ""
for c in plain_text:
    x = ord(c)
    x = x + 1
    c2 = chr(x)
    encrypted_text = encrypted_text + c2
print(encrypted_text)

Vastaavasti tämä viimeinen koodiesimerkki tekee päin vastaisen 'muunnoksen'. Eli vähennetään UTF-8 koodiarvosta luku 1 ja muutetaan koodi takaisin merkiksi. Syöttämällä tähän koodiin edellä olleen esimerkin merkkijonon, saadaan merkkijonon 'salaus' palautettua 'ymmärrettäväksi' lauseeksi.

fig.decryption
# Sample Python/Pygame Programs
# Simpson College Computer Science
# http://programarcadegames.com/
# http://simpson.edu/computer-science/

# Explanation video: http://youtu.be/sxFIxD8Gd3A

encrypted_text = "Uijt!jt!b!uftu/!BCD!bcd"

plain_text = ""
for c in encrypted_text:
    x = ord(c)
    x = x - 1
    c2 = chr(x)
    plain_text = plain_text + c2
print(plain_text)

7.8 Assosiatiiviset taulukot

Pythonissa voidaan taulukkoindeksinä käyttää muutakin kuin numeroita. Tämä ominaisuus antaa mahdollisuuden luoda assosiatiivisen taulukon. Assosiatiivinen taulukko toimii näin: (voit kopioida koodin IDLE-editoriin ja tutkia sen toiminnan)

# Luodaan tyhjä assosiatiivinen taulukko
# (Huomaa aaltosulkeet)
x = {}

# Luodaan taulukkoon alkioita
x["fred"] = 2
x["scooby"] = 8
x["wilma"] = 1

# tulostetaan merkki-indeksiin liitetty arvo
print(x["fred"])

Assosiatiivisia taulukoita tuskin tulet tarvitsemaan tällä kurssilla. Mutta on hyvä tietää tämäkin mahdollisuus

7.9 Review

7.9.1 Multiple Choice Quiz

Klikkaa tästä monivalintatehtävään.

7.9.2 Short Answer Worksheet

Klikkaa tästä kappaleen kertaustehtäviin.

7.9.3 Lab

Klikkaa tästä ohjelmointitehtäviin.


You are not logged in. Log in here and track your progress.