Kirjautuminen

Haku

Tehtävät

Keskustelu: Ohjelmointikysymykset: Python: python lista

Sivun loppuun

setä [22.02.2011 08:55:48]

#

Olen python-noviisi. Pitääkö tehdä jotain erikoista saadakseen käyttöön ison listan, jossa indeksit ulottuvat alueelle 1...15000000. Kun yritän asettaa tietylle listan alkiolle arvoa niin ei onnistu millään. If-lauseella onnistun kyllä testaamaan että arvo = 0 tai siitä ei ainakaan valita. Indeksille i on määrätty arvo mutta t(i) = 1 tai t(i) += 1 ei toimi. Alussa olen määrittänyt tyhjän listan rivillä t = []. Mitä puuttuu?

L2-K2 [22.02.2011 09:07:40]

#

Pythonissa listaa ei voi luoda halutun kokoiseksi, vaan sinne lisätään yksittäisiä alkioita kunnes haluttu koko on saavutettu.

Haluat mahdollisesti käytää sanakirjaa (dictionary). Tämä on erityisesti kannattavaa, jos suurin osa indekseistä ei ole käytössä.

%alustus
t = {}

%lisäys
t[100] = 1

%haku
if t.has_key(i):
    value = t[i]

%poisto
if t.has_key(i):
    del t[i]

setä [22.02.2011 09:24:27]

#

Epäilinkin vessassa että indeksi on ympäröitävä hakasuluilla. lista on kokonaislukulista. Aloittelijan moka!
Nyt se ilmoittaa: list index out of range
Eli miten tuo listan ulottuvuus määritellään. VB:ssä on määrittely:
Dim t(15000000) As Long, mutta miten pythonissa? En löytänyt oppaasta ohjetta tähän. Olen kai huono hakemaan.

-tossu- [22.02.2011 09:50:40]

#

setä kirjoitti:

Nyt se ilmoittaa: list index out of range
Eli miten tuo listan ulottuvuus määritellään. VB:ssä on määrittely:
Dim t(15000000) As Long, mutta miten pythonissa?

Näyttää siltä, että käytät tuossa vieläkin listaa sanakirjan sijasta. Huomaa, että lista määritellään hakasuluilla ja sanakirja aaltosuluilla, mutta molempiin viitataan kuitenkin hakasuluilla. Pythonissa sanakirjan kokoa ei tarvitse määritellä, vaan se kasvaa sitä mukaa kun siihen lisää dataa.

setä [22.02.2011 10:04:41]

#

Onko pythonissa lista jokin tietty taulukko ja sanakirja jokin toinen taulukko. En mitään sanakirjaa ole värkkäämässä vaan kokonaislukutaulukkoa. Siis määrittely hakasulkujen sijaan kaarisuluilla! Nyt tulee:
IndexError: tuple index out of range
TypeError: 'tuple' object does not support item assignment
Miten ihmeessä pythoniin saa ison kokonaislukutaulukon, jossa kaikki indeksit ovat käytössä? Vai eikö tuo kieli sellaista sisällä lainkaan???

-tossu- [22.02.2011 10:11:14]

#

setä kirjoitti:

Onko pythonissa lista jokin tietty taulukko ja sanakirja jokin toinen taulukko. En mitään sanakirjaa ole värkkäämässä vaan kokonaislukutaulukkoa. Siis määrittely hakasulkujen sijaan kaarisuluilla!

Sanakirja poikkeaa listasta siten, että sanakirjan indeksit voivat olla mitä tahansa kuten vapaavalintaisia lukuja tai merkkijonoja. Jos yrität määritellä listaa kaarisuluilla, saat tuplen, jota ei voi muokata, eli siitä tuskin on hyötyä sinulle.

Jos sinulla on aivan pakottava tarve luoda lista, jossa on 15000000 alkiota arvolla 0, onnistuu se näin.

lista = [0] * 15000000

setä kirjoitti:

Miten ihmeessä pythoniin saa ison kokonaislukutaulukon? Vai eikö tuo kieli sellaista sisällä lainkaan???

Pythonissa ei ole tiukkaa tyypitystä, joten siinä ei ole erikseen kokonaislukutaulukkoja.

setä [22.02.2011 10:14:16]

#

No just tuo on pakko tehdä, kiitos.

setä [22.02.2011 15:46:57]

#

Sain viimein simulaationi pelittämään mutta python on jumalattoman hidas. VB:llä homma hoituu paljon sukkelammin mutta satunnaisluku on rajallinen ja muutenkin numeroiden määrä. Mikä olisi sopiva kieli, onko pakko ruveta vanhana opiskelemaan jotain C++ vai mikä olisi passeli kieli VB:n jälkeen.

Chiman [22.02.2011 16:01:39]

#

Jos kerrot millaisen simulaation teit, voisimme vinkata mahdollisesti parempaa toteutusta Pythonilla.

C++ taipunee kaikkeen mitä yrität, mutta vaatii jonkin verran opettelua.

setä [22.02.2011 18:55:02]

#

Asensin itselleni Pythonin version 2.7.1 64-bittiseen Windows 7:ään. Piti arpoa satunnaisesti kokonaislukuja väliltä 0...15 milj. ja ilmaista arvontojen määrä kun enää yksi luku oli arpomatta ja kun lopulta se viimeinenkin tuli arvottua.

# -*- coding: latin-1 -*-
import random

for j in range(10):
    t = [0]*15380937
    s = 0
    n = 0
    f = 0
    while s < 15380937:
        i = random.randint(0, 15380936)
        if t[i] == 0:
            t[i] = 1
            s += 1
        n += 1
        if s == 15380936 and f == 0:
            n1 = n
            f = 1
    print n1, n

VB:llä 20 kierroksen arvontaan meni muutama minuutti mutta tämän koodin pyöritys vei noin 1,5 h.

Mizou [22.02.2011 19:51:56]

#

for j in range(10):
    t = {}
    s = 0
    n = 0
    f = 0
    while s < 15380937:
        i = random.randint(0, 15380936)
        if t.get(i, 0) == 0:
            t[i] = 1
            s += 1
        n += 1
        if s == 15380936 and f == 0:
            n1 = n
            f = 1
    print n1, n

Siinä sama Dictionarylla (En viellä testannut) kuten yllä ehdotettiin, ottamatta kantaa itse koodiin.

Edit. Pääsinkin jo testaamaan ja toimii.
Edit2. get:in tilalle kävisi tietysti myös has_key(). get on parempi tietyissa tapauksissa, mutta en tiedä onko niillä suuria nopeuseroja.

setä [22.02.2011 20:18:47]

#

Laitoin pyörimään mutta hitaalta vaikuttaa tämäkin. Pitikö sen näin toimia nopeammin vai miksi tämä olisi suositeltavampi ratkaisu?
Edit: Näyttää kestävän yli 2 tuntia. Mittaampa nopeuden hieman tarkemmin.

Mizou [22.02.2011 20:22:01]

#

Nopeudesta en tiedä, luultavasti ei suuria eroja (joku viisaampi voi kertoa?). Etuna lähinnä se ettei tarvitse määritellä kokoa vaan koko kasvaa sitä mukaan kuin tarvitaan.

Chiman [22.02.2011 20:29:33]

#

Noita erilaisten toteutusten nopeuseroja kannattaisi testata vaikka sata kertaa pienemmällä taulukolla, jotta suoritusaika on noin 10-60 s.

Veikkaan listaa nopeammaksi tuossa tapauksessa, koska kaikkia alkioita tarvitaan. Sanakirjasta (dictionary, {}) on etua muistin säästämisessä, jos vain pientä osaa lukualueesta oikeasti käytetään. Kolmas vaihtoehto on joukko (set).

setä [22.02.2011 21:51:08]

#

Tein mittausversiot molemmista. Lista oli hieman nopeampi, miljoona arvontaa 2,9 sekunnissa ja kirjastona 3,5 s.
Käytin apuna Antin kirjoittamaa Python-opasta. Kuinkahan tuota joukkoa tässä käytetään ja mistä tähän Pythoniin saa tarkempaa tietoa, mieluummin suomeksi?

Metabolix [22.02.2011 22:27:17]

#

Pythonissa varsinainen pullonkaula saattaa olla tuo funktiokutsu.

Ajoin testin 100000 luvulla ja alustuksella random.seed(0). Arvontoja tuli tällöin ajettua 1150713. Listaan perustuva versio vei 4,3 sekuntia. Set-versio tyhjästä täyteen päin vei 4,7 sekuntia ja set-versio täydestä tyhjään päin vei 4,5 sekuntia. (Näiden ero on siinä, että kun set aluksi sisältää kaikki ja lukuja poistetaan, setin koko keskimäärin on pienempi, koska viimeisiä lukuja joudutaan hakemaan pidempään kuin ensimmäisiä.) Täsmälleen sama määrä pelkkiä arvontoja ilman kirjanpitoa vei jo 4,0 sekuntia.

setä [24.02.2011 11:56:05]

#

Ajoin vielä testin VB5:llä ja miljoonaan arvontaan kirjanpitoineen meni melko tarkasti 80 ms.

Chiman [24.02.2011 12:23:33]

#

Yleisimmän ja tuetuimman Python-toteutuksen (CPython) tilalla voi kokeilla suorituskykyisempää PyPyä.

Täytin sadantuhannen alkion kokoisen taulukon kymmenen kertaa:

CPython (Python 2.6.4):

$ time python test.py
1114711 1163988
1046070 1180377
1108874 1161013
1101852 1173923
1016151 1032114
1119036 1319794
1025606 1026722
1065318 1136217
1193189 1207619
1179027 1183550

real	0m32.061s
user	0m32.050s
sys	0m0.010s

PyPy:

$ time ~/pypy-1.4/bin/pypy test.py
1054526 1068945
1033222 1260999
1251017 1266189
1068709 1116446
1077002 1113051
1168525 1235442
1116246 1262609
1028934 1055615
1071553 1075678
1075551 1079500

real	0m2.439s
user	0m2.410s
sys	0m0.030s

setä [24.02.2011 12:57:29]

#

Onkos tuo PyPy ilmainen ja mistä ladattavissa?

Chiman [24.02.2011 12:59:24]

#

Edellisessä viestissäni olevan linkin takaa näyttäisi löytyvän 32-bit Windows-binääri.

setä [24.02.2011 16:51:10]

#

Kovin on ruuhkainen palvelin kun tulee muutama 10 tavua sekunnissa. Ei meinaa onnistua lataus millään.

Metabolix [24.02.2011 17:02:34]

#

Kyllä tuo minulla latautui ihan parissa sekunnissa osoitteesta http://pypy.org/download/pypy-1.4.1-win32.zip, joten tarkistapa oma nettiyhteytesi.

setä [24.02.2011 17:19:49]

#

Mulla on saunalahden 1 Mbit/s yhteys ja yleensä latausnopeus on 112 B/s. Mutta tuosta osoitteesta tulee huomattavasti hitaammin ja lopulta katkeaa kokonaan.

Pessi [24.02.2011 17:30:34]

#

Kokeiles http://pessi.kapsi.fi/pypy-1.4.1-win32.zip tuosta ladata.

setä [24.02.2011 17:44:43]

#

Kiitos, sieltähän se tuli ongelmitta.

setä [10.03.2011 12:55:00]

#

Chiman, voitko antaa pari vinkkiä, miten tuota PyPyä käytetään. Miten sinne saa olemassa olevan ohjelman, miten se käännetään ja ajetaan?
Voiko Pythonilla käsitellä myös binääritiedostoja tekstitiedostojen lisäksi?

Chiman [10.03.2011 13:17:52]

#

PyPyä käytetään niin, että ajetaan Python-kooditiedosto käyttäen PyPy-binääriä normaalin Python-binäärin sijasta. Ei siinä mitään erillistä käännösvaihetta ole, vaan PyPy hoitaa sisäisesti kaiken tarvittavan. Windows-versiota en ole kokeillut, joten en osaa antaa tarkkoja komentoja.

Linuxilla purin pypy-paketin kotihakemistooni, jolloin ajokomento oli:

~/pypy-1.4/bin/pypy test.py

Pythonilla voi käsitellä myös binääritiedostoja.

setä [10.03.2011 16:04:15]

#

Kun tallensin python-tiedoston samaan kansioon, jossa pypy.exe on, toimi komennolla pypy tiedosto. Mutta ohjelma ajoi vain yhden for-silmukan ja ilmoitti virheestä vaikka pythonilla (2.7) ohjelma toimi oikein. Pypy on kai tehty versiolla 2.5. Johtuneeko tosta versioiden erosta. kesti kuitenkin yli kolme minuuttia sen yhden arvonnanryppään suoritus, siis noin 2,6 E8 arvontaa.

Chiman [10.03.2011 16:16:29]

#

PyPy ei tue kaikkia CPythonin mukana tulevia kirjastoja, joten PyPy ei sovellu kaikkiin käyttötapauksiin. Pastea virheilmoitus ja mahdollisesti siihen liittyvää koodia, jos haluat vinkkiä.

setä [10.03.2011 16:38:18]

#

En nyt muista kuinka saan tosta komentoikkunasta mitään kopsattua.
Koodi on tuolla ylempänä. Virhe tuli toisen for-silmukan alkuun rivillä 12 t(i) = 1 (piti olla hakasulut mutta siitä tulikin italic). En nyt muista mitä kaikkea herjaa se heitti mutta ajan uudelleen ja kopioin vaikka käsin.

Traceback (most recent call last):
  File "app_main.py", line 53, in run_toplevel
  File "test1", line 15, in <module>
    t[i] = 1
MemoryError

Eka silmukka meni virheettä ja myös toinen jonkin aikaa. Koodiin on lisätty ajanmittauskäskyt, muuten sama kuin yllä. (Kuinkahan nuo hakasulut saa tungettua tuonne ilman että heittää tekstin kursiiviksi.) (Mod. vastaa: tageilla [h] ja [/h] tai käyttämällä kooditagia.)


Sivun alkuun

Vastaus

Aihe on jo aika vanha, joten et voi enää vastata siihen.

Tietoa sivustosta