Python: efektívny lovec / 5. časť

0

List

List je sekvenčné zoskupenie položiek (items), resp. elementov rôznych typov do jedného celku, ktorý ohraničujeme hranatými zátvorkami. Rovnako ako typ tuple môžeme vytvárať vnorené (nested) listy, kde je jeden list položkou iného listu. Na získanie konkrétnej položky listu používame rovnaký indexovací operátor ako v prípade typu string. Mnohé ďalšie metódy a operátory typu string, ako napr. len(), for element in list, in, not in…, sú adekvátne použiteľné aj v prípade typu list. Operátor + sa používa na spájanie (concatenate) a operátor * na opakovanie listov.

Najdôležitejší rozdiel typu list oproti typom string a tuple je ten, že typ list je meniteľný (mutable). To znamená, že jednotlivé položky premennej typu list môžeme kedykoľvek zmeniť. Pre typ list je navyše definovaná metóda del(), pomocou ktorej môžeme konkrétne položky zmazať.

List aliasing a klonovanie

Z dôvodu, že typ list je meniteľný, pre dva rovnaké listy nikdy nebude vyhradené rovnaké pamäťové miesto, čo je v kontraste s typmi string a tuple. No ak priradíme jednu premennú typu list inej premennej typu list, obe budú ukazovať na rovnaké pamäťové miesto. Vytvoríme tak alias, čo znamená, že len čo zmeníme niektorú položku jednej premennej, rovnako sa zmení tá istá položka aj pri druhej premennej. To platí aj pre používanie typov list ako argumentov volaných funkcií.

V prípade, ak chceme priradiť jednu premennú typu list inej premennej bez odkazu na to isté pamäťové miesto, robíme tak pomocou operátora slice. V takom prípade sa vždy vytvorí (naklonuje) nový list (nový objekt), na ktorý bude ukazovať druhá premenná:

premenná   a:        a = [1,2,3]
klon premennej a:   b = a[:]

Použitie typu list demonštrujeme na príklade č. 5, ktorý cestou funkcií rieši jednoduchú vektorovú algebru:

# Sčítanie dvoch 3-rozmerných vektorov u,v

def vector_add(u,v):

    assert len(u) == len(v) == 3

    return [u[0] + v[0],u[1] + v[1],u[2] + v[2]]


# Odčítanie dvoch 3-rozmerných vektorov u,v

def vector_sub(u,v):

    assert len(u) == len(v) == 3

    return [u[0] - v[0],u[1] - v[1],u[2] - v[2]]


# Násobenie 3-rozmerného vektora u skalárom s

def vector_mul(u,s):

    assert len(u) == 3

    return [u[0] * s,u[1] * s,u[2] * s]


# Skalárny súčin dvoch 3-rozmerných vektorov u,v

def dot_product(u,v):

    assert len(u) == len(v) == 3

    return (u[0] * v[0] + u[1] * v[1] + u[2] * v[2])

 

# Vektorový súčin dvoch 3-rozmerných vektorov u,v

def cross_product(u,v):

    assert len(u) == len(v) == 3

    return [u[1] * v[2] - u[2] * v[1],

            u[2] * v[0] - u[0] * v[2],

            u[0] * v[1] - u[1] * v[0]]


v1 = [1.0,0.0,0.0]; v2 = [0.0,1.0,0.0]; s0 = 10.0


print("Vektory:\n-----------------------------------------")

print("v1 =",v1,"\nv2 =",v2,"\n-----------------------------------------")


print("Sčítanie:               ",vector_add(v1,v2))

print("Odčítanie:              ",vector_sub(v1,v2))

print("Násobenie skalárom:      v1 *",s0,"=",vector_mul(v1,s0))

print("                         v2 *",s0,"=",vector_mul(v2,s0))

print("Skalárny súčin:         ",dot_product(v1,v2))

print("Vektorový súčin:        ",cross_product(v1,v2))

Pri práci s typom list sa často používa funkcia enumerate() a metódy ako napr.

append()

doplnenie položky do záznamu

insert()

vloženie položky na konkrétnu
pozíciu v zázname

extend()

rozšírenie záznamu o nové položky

count()

spočítanie výskytu položky
v zázname

index()

získanie indexu položky v zázname

sort()

zoradenie položiek záznamu

remove()

odstránenie položky zo záznamu

Dict

Slovníky sú meniteľný dátový typ, ktorý mapuje nemeniteľné kľúče (keys) k ľubovoľným typom údajov. Hovoríme im aj asociatívne polia, pretože kľúčom priraďujú hodnoty. Slovníky podobne ako tuple a listy ohraničujeme zátvorkami, v tomto prípade zloženými zátvorkami. Kľúče sú od hodnôt oddelené dvojbodkou, jednotlivé páry sú od seba oddelené čiarkou, a čo je veľmi dôležité, páry nie sú zoradené (nie sú indexovateľné). Typ dict teda nie je sekvenčný typ. Prednosťou slovníkov, ktoré možno inak zapísať aj pomocou listov s typmi tuple, je ich rýchlosť. Python totiž na sprístupnenie jednotlivých párov slovníka používa efektívny hašovací algoritmus.


Príklad č. 5

Operácie so slovníkmi

Slovníky sú meniteľné typy, z čoho vyplýva, že pre ne platia rovnaké pravidlá týkajúce sa vytvárania aliasov a kópií ako v prípade typu list. Príklady operácií, ktoré môžeme vykonávať so slovníkmi:

len()

dĺžka slovníka

del()

odstránenie páru zo slovníka

keys()

podobne ako range() v okamihu, keď je to potrebné, vracia pár zo slovníka

values()

items()

vráti objekt view, ktorý môže byť transformovaný na typ list, resp. typ tuple

copy()

vytvorí nový objekt typu dict klonovaním z pôvodného objektu

V rámci príkladu č. 6 využívame typ slovník na výpočet početnosti znakov v texte:

text = str(input("Zadaj text: "))


# typ dict, naplní sa pármi znak:početnosť

pocetnost_znakov = {}

i = 0

# pre každý znak v zadanom texte

for znak in text:

    i += 1

    # zvýšenie početnosti konkrétneho znaku

    pocetnost_znakov[znak] = pocetnost_znakov.get(znak,0)+1


print("Celkový počet znakov v zadanom texte je:",i)

print("Početnosť jednotlivých znakov v texte je:")

print(pocetnost_znakov)

Moduly

Modul je súbor, ktorý obsahuje definície a výkonné výrazy, ktoré môžeme využiť v rámci našich programov. Navzájom súvisiace moduly je zvykom spájať do jednotného celku, ktorý nazývame knižnica (library). Takouto knižnicou je aj štandardná knižnica Pythonu, v ktorej môžeme okrem iných nájsť aj nasledujúce moduly (tab. 1).

Vytvorenie vlastného modulu je veľmi jednoduché. V podstate stačí, ak náš kód uložíme do súboru s príponou .py. Následne v inom súbore náš modul pripojíme pomocou jednej z troch možností:

1. import názov_súboru (bez prípony .py) - čo je ekvivalentné s import názov_modulu

2. import názov_modulu as nový_názov – pripojenie modulu pod novým názvom

3. from názov_modulu import */funkcia/atribút – priame vloženie */funkcií/atribútov do aktuálneho namespace

Funkcie, resp. premenné (atribúty), ktoré sme definovali v našom module, voláme pomocou klasického zápisu s bodkou:

názov_modulu.funkcia()

názov_modulu.atribút

Príklad č. 6

Menné priestory

Menné priestory (namespaces) sú kolekcie identifikátorov, ktoré patria konkrétnemu modulu, resp. funkcii. Každý modul má vlastný menný priestor, čo znamená, že dva rozdielne moduly môžu obsahovať identifikátory s rovnakým názvom. Ich odlíšenie sa rieši práve cestou zápisu s bodkou, v rámci ktorého je jednoznačne určený modul, ktorému daný identifikátor patrí.

Rozsah platnosti

Rozsah platnosti (scope) identifikátorov súvisí s mennými priestormi. Python rozlišuje medzi tromi rozsahmi platnosti identifikátorov:

1. lokálny – platí v rámci funkcie,

2. globálny – platí v rámci modulu (súboru),

3. zabudovaný (built-in) – identifikátory preddefinované v Pythone.

Pri vyhodnocovaní, ktorý identifikátor sa použije, majú prednosť (prioritu) lokálne identifikátory pred globálnymi a globálne pred zabudovanými.


Príklad č. 7

Modul NumPy

Premenné typu list nemajú charakter objektov, s ktorými je vhodné vykonávať matematické operácie. Z uvedeného dôvodu bol do Pythonu doplnený modul numpy, ktorý okrem vykonávania základných matematických výpočtov umožňuje pracovať s:

n n-rozmernými poľami (maticami),

n kódom písaným v jazykoch C/C++ a Fortran,

n lineárnou algebrou,

n Fourierovými transformáciami,

n náhodnými číslami.

Pri práci s modulom numpy dochádza k automatickej konverzii sekvenčných dátových typov na typ pole (array) a naopak. Tento konverzný typ nazývame dtype (data type), pričom najčastejšie pracujeme s variantmi číselných typov int a float. S premennými typu numpy dokážeme vykonávať mnoho rovnakých operácií ako s typom list, ibaže v prípade viacrozmerných polí nepracujeme s hodnotami, ale s poľami hodnôt.

Príklad č. 7 využíva funkcie modulov Matplotlib a NumPy na vizualizáciu dát:

# state-machine environment

import matplotlib.pyplot as plt

import numpy as np


# figure, axes

fig,ax = plt.subplots()


# nastavenie axes

ax.set(xlim = [0,10],ylim = [-2,20],

       xlabel = "x",ylabel = "y",

       title = "Jednoduché funkcie")


# vráti pole rovnomerne rozložených číslic [start,stop,počet]

x = np.linspace(0,10,100)

ax.plot(x,x,label = "Lineárna")

ax.plot(x,x**2,label = "Kvadratická")

ax.plot(x,x**3,label = "Kubická")


# vráti pole rovnomerne rozložených číslic [start,stop,krok]

x = np.arange(0.0,11.0,0.1)

# vráti pole - výsledky výpočtu sin(x)

y = 2*np.sin(x)

ax.plot(x,y,label = "Sínusoida")


ax.legend()

ax.grid()


plt.show()

 

Zobrazit Galériu

Marek Sopko

Všetky autorove články
Python

Pridať komentár