Bežne používaná základná syntax Pythonu v dátovej vede
Posledných pár dní som čítal knihu Data Science from Scratch (PDF adresa). Je to výborná, ľahko pochopiteľná úvodná kniha do dátovej vedy. Jedna z kapitol predstavuje základnú syntax Pythonu a pokročilú syntax bežne používanú v dátovej vede. Považoval som to za veľmi dobre a jasne vysvetlené, preto som sa rozhodol to preložiť a zdieľať tu ako poznámky pre budúcnosť. Bežne používaná základná syntax Pythonu v dátovej vede (základy) Bežne používaná pokročilá syntax Pythonu v dátovej vede
Táto kapitola sa zameriava na predstavenie základnej syntaxe a funkcií Pythonu (založených na verzii Python 2.7), ktoré sú mimoriadne užitočné pri spracovaní dát.
Formátovanie medzier
Mnohé programovacie jazyky používajú na riadenie blokov kódu zátvorky, no Python namiesto nich využíva odsadenie:
for i in [1, 2, 3, 4, 5]:
print i # prvý riadok cyklu "for i"
for j in [1, 2, 3, 4, 5]:
print j # prvý riadok cyklu "for j"
print i + j # posledný riadok cyklu "for j"
print i # posledný riadok cyklu "for i"
print "cyklus dokončený"
Vďaka tomu je kód v Pythone veľmi ľahko čitateľný, ale zároveň to znamená, že si musíte neustále dávať pozor na formátovanie. Medzery v zátvorkách sú ignorované, čo je užitočné pri písaní dlhých výrazov:
long_winded_computation = (1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + 15 + 16 + 17 + 18 + 19 + 20)
Tiež to zlepšuje čitateľnosť kódu:
list_of_lists = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
easier_to_read_list_of_lists = [ [1, 2, 3],
[4 ,5 ,6 ],
[7 ,8 ,9 ] ]
Viacriadkové príkazy
Na spojenie dvoch riadkov, ktoré sú inak prerušené, môžete použiť spätnú lomku (tento postup sa však používa zriedkavo):
two_plus_three = 2 + \
3
Moduly
Či už ide o moduly vstavané v Pythone alebo moduly tretej strany, ktoré si stiahnete, všetky sa musia ručne importovať, aby ste ich mohli použiť.
- Jednoduchý priamy import celého modulu:
import re
my_regex = re.compile("[0-9]+", re.I)
Modul re importovaný v tomto príklade slúži na regulárne výrazy. Po importovaní modulu môžete priamo volať jeho funkcie pomocou názvu modulu ako predpony (napr. re.).
- Ak sa názov importovaného modulu už používa vo vašom kóde, môžete ho pri importe premenovať:
import re as regex
my_regex = regex.compile("[0-9]+", regex.I)
- Ak by ste chceli byť „zlí“, môžete importovať celý modul do aktuálneho menného priestoru, čo môže neúmyselne prepísať vami už definované premenné:
match = 10
from re import * # Modul re obsahuje funkciu match
print match # Vypíše funkciu match
Pretože ste dobrý človek, verím, že to robiť nebudete.
Aritmetické operácie
Python 2.7 predvolene používa celočíselné delenie, takže $ 5 / 2 = 2 $. No v mnohých prípadoch nechceme celočíselné delenie, preto môžeme importovať tento modul:
from __future__ import division
Po importe dostaneme $5 / 2 = 2.5$. Celočíselné delenie: $5 // 2 = 2$.
Funkcie
Definícia funkcie
Funkcia je pravidlo, ktoré prijíma nula alebo viac vstupov a vracia určitý výstup. V Pythone definujeme funkciu pomocou def nazov_funkcie(parametre):
def double(x):
"""Tu môžete napísať vysvetlenie funkčnosti funkcie,
napríklad, že táto funkcia vynásobí vstup dvoma."""
# Tu môžete písať telo funkcie, nezabudnite na odsadenie
return x * 2
Používanie funkcií
V Pythone sú funkcie objekty prvej triedy, čo znamená, že ich môžeme priradiť premennej alebo ich odovzdať ako argumenty iným funkciám:
def apply_to_one(f):
"""Zavolá funkciu f a odovzdá jej 1 ako parameter"""
return f(1)
my_double = double # double odkazuje na funkciu definovanú v predchádzajúcej sekcii
x = apply_to_one(my_double) # x sa rovná 2
Anonymné funkcie
Anonymné funkcie môžeme vytvárať aj pomocou príkazu lambda:
y = apply_to_one(lambda x: x + 4) # rovná sa 5
Aj keď môžete priradiť lambda premenným, väčšina ľudí vám odporučí, aby ste radšej používali def:
another_double = lambda x: 2 * x # Neodporúča sa
def another_double(x): return 2 * x # Odporúčaný postup
Doplnenie:
lambdaje len výraz, telo funkcie je oveľa jednoduchšie ako pridef.- Telo
lambdaje výraz, nie blok kódu. Do výrazulambdaje možné zapuzdriť len obmedzenú logiku.
Odovzdávanie parametrov funkciám
Parametre funkcie môžu mať definované predvolené hodnoty. Ak sa funkcia zavolá bez argumentov pre tieto parametre, použijú sa predvolené hodnoty; ak sa argumenty zadajú, prenesú sa zadané hodnoty:
def my_print(message="my default message"):
print message
my_print("hello") # Vypíše "hello"
my_print() # Vypíše "my default message"
Niekedy je tiež veľmi užitočné špecifikovať argumenty priamo pomocou ich názvov:
def subtract(a=0, b=0):
return a - b
subtract(10, 5) # Vráti 5
subtract(0, 5) # Vráti -5
subtract(b=5) # Rovnaké ako predchádzajúce, vráti -5
Reťazce
Reťazce môžete vytvárať pomocou jednoduchých alebo dvojitých úvodzoviek (úvodzovky musia byť vždy spárované):
single_quoted_string = 'data science'
double_quoted_string = "data science"
Spätná lomka sa používa na označenie riadiacich znakov, napr.:
tab_string = "\t" # predstavuje tabulátor
len(tab_string) # rovná sa 1
Ak chcete použiť samotnú spätnú lomku (napr. pre cesty k súborom vo Windowse alebo regulárne výrazy), môžete ju definovať pomocou raw stringu r"":
not_tab_string = r"\t" # predstavuje znaky '\' a 't'
len(not_tab_string) # rovná sa 2
Viacriadkové reťazce vytvoríte pomocou troch dvojitých úvodzoviek:
multi_line_string = """Toto je prvý riadok
Toto je druhý riadok
Toto je tretí riadok"""
Spracovanie výnimiek
Keď program narazí na chybu, Python vyvolá výnimku. Ak ju nespracujeme, program sa ukončí. Výnimky môžeme zachytiť pomocou príkazov try a except:
try:
print 0 / 0
except ZeroDivisionError:
print "Nemožno deliť nulou"
Zatiaľ čo v iných jazykoch sú výnimky často vnímané ako neželané javy, v Pythone môže rozsiahlejšie spracovanie výnimiek viesť k čistejšiemu a stručnejšiemu kódu.
Zoznamy
Vytvorenie zoznamu
Zoznamy sú jednoduché usporiadané kolekcie a sú jednou z najzákladnejších dátových štruktúr v Pythone (podobné poliam v iných jazykoch, ale s niektorými dodatočnými vlastnosťami). Vytvorenie zoznamu:
integer_list = [1, 2, 3]
heterogeneous_list = ["string", 0.1, True]
list_of_lists = [ integer_list, heterogeneous_list, [] ]
list_length = len(integer_list) # rovná sa 3
list_sum = sum(integer_list) # rovná sa 6
Prístup k hodnotám v zozname
Hodnoty v zozname môžete indexovať pomocou hranatých zátvoriek:
x = range(10) # Získa zoznam x = [0, 1, ..., 9]
zero = x[0] # rovná sa 0, indexovanie zoznamu začína od 0
one = x[1] # rovná sa 1
nine = x[-1] # rovná sa 9, posledný prvok v zozname
eight = x[-2] # rovná sa 8, predposledný prvok v zozname
x[0] = -1 # Aktuálny zoznam x = [-1, 1, 2, 3, ..., 9]
Krájanie zoznamu
Zoznamy môžete krájať (slice) pomocou hranatých zátvoriek:
first_three = x[:3] # [-1, 1, 2]
three_to_end = x[3:] # [3, 4, ..., 9]
one_to_four = x[1:5] # [1, 2, 3, 4]
last_three = x[-3:] # [7, 8, 9]
without_first_and_last = x[1:-1] # [1, 2, ..., 8]
copy_of_x = x[:] # [-1, 1, 2, ..., 9]
Pomocou operátora in môžete skontrolovať, či sa daný prvok nachádza v zozname:
1 in [1, 2, 3] # True
0 in [1, 2, 3] # False
Tento spôsob vyhľadávania prvkov je veľmi neefektívny. Používajte ho len vtedy, ak je zoznam malý alebo ak vám nezáleží na čase vyhľadávania.
Spájanie zoznamov
V Pythone je spájanie dvoch zoznamov veľmi jednoduché:
x = [1, 2, 3]
x.extend([4, 5, 6]) # Aktuálne x = [1,2,3,4,5,6]
Ak nechcete modifikovať pôvodný zoznam x, môžete použiť operátor + na vytvorenie nového zoznamu:
x = [1, 2, 3]
y = x + [4, 5, 6] # Aktuálne y = [1, 2, 3, 4, 5, 6]; x zostáva nezmenené
Často sa používa tento spôsob na pridanie jedného prvku do zoznamu naraz:
x = [1, 2, 3]
x.append(0) # Aktuálne x = [1, 2, 3, 0]
y = x[-1] # rovná sa 0
z = len(x) # rovná sa 4
Rozbaľovanie zoznamov
Ak viete, koľko prvkov má zoznam, je veľmi ľahké ho rozbaliť:
x, y = [1, 2] # Aktuálne x = 1, y = 2
Ak sa počet prvkov na oboch stranách rovnice nezhoduje, dostanete ValueError. Preto často používame podčiarkovník na uchovanie zvyšku zoznamu:
_, y = [1, 2] # Aktuálne y == 2, prvý prvok sa ignoruje
N-tice (Tuples)
Zoznamy a n-tice sú si veľmi podobné. Jediný rozdiel je v tom, že prvky v n-ticiach nemožno modifikovať.
Vytvorenie n-tice
N-tice možno vytvárať pomocou okrúhlych zátvoriek alebo bez akýchkoľvek zátvoriek:
my_tuple = (1, 2)
other_tuple = 3, 4
my_list[1] = 3 # Aktuálne my_list je [1, 3]
try:
my_tuple[1] = 3
except TypeError:
print "N-ticu nemožno modifikovať"
N-tice sú veľmi užitočné na vrátenie viacerých hodnôt z funkcie:
def sum_and_product(x, y):
return (x + y),(x * y)
sp = sum_and_product(2, 3) # rovná sa (5, 6)
s, p = sum_and_product(5, 10) # s = 15, p = 50
N-tice (a zoznamy) podporujú priradenie viacerých prvkov naraz:
x, y = 1, 2 # Aktuálne x = 1, y = 2
x, y = y, x # Výmena hodnôt dvoch premenných v Pythone; aktuálne x = 2, y = 1
Slovníky (Dictionaries)
Vytvorenie slovníka
Ďalšou základnou dátovou štruktúrou v Pythone je slovník, ktorý vám umožňuje rýchlo zísť priradenú hodnotu (value) pomocou kľúča (key):
empty_dict = {} # Veľmi "pythonovská" definícia prázdneho slovníka
empty_dict2 = dict() # Menej "pythonovská" definícia prázdneho slovníka
grades = { "Joel" : 80, "Tim" : 95 } # Uloženie slovníka
Vyhľadávanie prvkov v slovníku
Priradenú hodnotu môžete nájsť pomocou hranatých zátvoriek a kľúča:
joels_grade = grades["Joel"] # rovná sa 80
Ak hľadaný kľúč v slovníku neexistuje, vráti sa KeyError:
try:
kates_grade = grades["Kate"]
except KeyError:
print "žiadna známka pre Kate!"
Pomocou operátora in môžete skontrolovať, či sa kľúč nachádza v slovníku:
joel_has_grade = "Joel" in grades # True
kate_has_grade = "Kate" in grades # False
Slovníky majú metódu, ktorá dokáže vrátiť predvolenú hodnotu, ak hľadaný kľúč v slovníku neexistuje (namiesto vyvolania výnimky):
joels_grade = grades.get("Joel", 0) # rovná sa 80
kates_grade = grades.get("Kate", 0) # rovná sa 0
no_ones_grade = grades.get("No One") # Vráti predvolenú hodnotu None
Úprava slovníka
Kľúč-hodnotové páry v slovníku môžete vytvárať a upravovať pomocou hranatých zátvoriek:
grades["Tim"] = 99 # Nahradí starú hodnotu
grades["Kate"] = 100 # Pridá kľúč-hodnotový pár
num_students = len(grades) # rovná sa 3
Často budeme používať slovníky na vyjadrenie štruktúry dát takto:
tweet = {
"user" : "joelgrus",
"text" : "Data Science is Awesome",
"retweet_count" : 100,
"hashtags" : ["#data", "#science", "#datascience", "#awesome", "#yolo"]
}
Okrem vyhľadávania konkrétnych kľúčov môžeme pracovať so všetkými kľúčmi nasledovne:
tweet_keys = tweet.keys() # Získa zoznam kľúčov
tweet_values = tweet.values() # Získa zoznam hodnôt
tweet_items = tweet.items() # Získa n-tice (kľúč, hodnota)
"user" in tweet_keys # Vráti True, používa menej efektívne vyhľadávanie 'in' v zozname
"user" in tweet # Viac "pythonovský" spôsob, používa efektívnejšie vyhľadávanie 'in' v slovníku
"joelgrus" in tweet_values # True
Kľúče v slovníku sú jedinečné a zoznamy nemožno použiť ako kľúče slovníka. Ak potrebujete viaczložkový kľúč, môžete použiť n-ticu alebo kľúč previesť na reťazec.
Predvolené slovníky (Defaultdicts)
Ak sa pokúšate spočítať frekvenciu každého slova v dokumente, zrejmým prístupom je vytvoriť slovník, kde slová slúžia ako kľúče a ich frekvencie ako priradené hodnoty. Potom prejdete dokument a pre každé už existujúce slovo zvýšite jeho počet o 1; pre neexistujúce slovo pridáte nový kľúč-hodnotový pár do slovníka:
word_counts = {}
for word in document:
if word in word_counts:
word_counts[word] += 1
else:
word_counts[word] = 1
Samozrejme, chýbajúci kľúč môžete vopred spracovať aj takýmto spôsobom (tzv. „ask for forgiveness, not permission“):
word_counts = {}
for word in document:
try:
word_counts[word] += 1
except KeyError:
word_counts[word] = 1
Tretia metóda je použitie get, ktorá výborne zvláda chýbajúce kľúče:
word_counts = {}
for word in document:
previous_count = word_counts.get(word, 0)
word_counts[word] = previous_count + 1
defaultdict funguje rovnako ako bežný slovník, s jediným rozdielom: keď sa pokúsite vyhľadať neexistujúci kľúč, defaultdict automaticky vytvorí kľúč-hodnotový pár pomocou funkcie, ktorú ste mu poskytli. Na použitie defaultdict musíte importovať knižnicu collections:
from collections import defaultdict
word_counts = defaultdict(int) # int() generuje 0
for word in document:
word_counts[word] += 1
defaultdict je tiež veľmi užitočný s funkciami ako list, dict alebo dokonca s vlastnými funkciami:
dd_list = defaultdict(list) # list() generuje prázdny zoznam
dd_list[2].append(1) # Aktuálne dd_list je {2: [1]}
dd_dict = defaultdict(dict) # dict() generuje prázdny slovník
dd_dict["Joel"]["City"] = "Seattle" # Aktuálne dd_dict obsahuje { "Joel" : { "City" : "Seattle"}}
dd_pair = defaultdict(lambda: [0, 0]) # Vytvorí slovník, kde hodnoty kľúčov sú zoznamy
dd_pair[2][1] = 1 # Aktuálne dd_pair obsahuje {2: [0,1]}
Táto metóda je veľmi užitočná, pretože v budúcnosti už nebudeme musieť kontrolovať existenciu kľúča pri získavaní hodnôt zo slovníka.
Počítadlo (Counter)
Počítadlo (Counter) dokáže priamo premeniť skupinu hodnôt na objekt podobný slovníku, kde kľúčom je prvok zo skupiny a priradenou hodnotou je počet výskytov tohto prvku. To sa často používa pri vytváraní histogramov:
from collections import Counter
c = Counter([0, 1, 2, 0]) # c je (približne) { 0 : 2, 1 : 1, 2 : 1 }
Týmto spôsobom získame veľmi pohodlnú metódu na počítanie frekvencie slov:
word_counts = Counter(document)
Počítadlo má aj veľmi užitočnú metódu most_common, ktorá dokáže priamo získať niekoľko najčastejších slov a ich frekvencie:
# Vypíše 10 najčastejších slov a ich počet
for word, count in word_counts.most_common(10):
print word, count
Množiny (Sets)
Ďalšou dátovou štruktúrou v Pythone sú množiny, ktoré predstavujú kolekciu rôznych prvkov. Množinu môžete vytvoriť a pridávať do nej prvky nasledovne:
s = set()
s.add(1) # s je { 1 }
s.add(2) # s je { 1, 2 }
s.add(2) # s je { 1, 2 }
x = len(s) # rovná sa 2
y = 2 in s # rovná sa True
z = 3 in s # rovná sa False
Dva hlavné dôvody pre používanie množín:
Po prvé, operácia in v množinách je veľmi efektívna. Keď je počet prvkov v dátovej sade veľmi veľký, vyhľadávanie prvkov vo forme množiny je zjavne vhodnejšie ako v zozname:
stopwords_list = ["a","an","at"] + hundreds_of_other_words + ["yet", "you"]
"zip" in stopwords_list # Neúspešné, je potrebné skontrolovať každý prvok
stopwords_set = set(stopwords_list)
"zip" in stopwords_set # Vyhľadávanie úspešné a veľmi rýchle
Po druhé, je veľmi pohodlné používať množiny na získanie jedinečných prvkov zo sady dát:
item_list = [1, 2, 3, 1, 2, 3]
num_items = len(item_list) # 6
item_set = set(item_list) # {1, 2, 3}
num_distinct_items = len(item_set) # 3
distinct_item_list = list(item_set) # [1, 2, 3]
V praxi sa však množiny nepoužívajú tak často ako slovníky a zoznamy.
Podmienené príkazy
Vo väčšine programovacích jazykov môžete použiť if na vyjadrenie podmienených vetiev takto:
if 1 > 2:
message = "keby len 1 bolo väčšie ako dva…"
elif 1 > 3:
message = "elif znamená 'else if'"
else:
message = "keď všetko ostatné zlyhá, použite else (ak chcete)"
Podmienený príkaz môžete napísať aj na jeden riadok, ale to sa používa zriedkavo:
parity = "even" if x % 2 == 0 else "odd"
Cykly
Cyklus while
Cyklus while v Pythone:
x = 0
while x < 10:
print x, "je menšie ako 10"
x += 1
Cyklus for
Častejšie sa používa cyklus for-in:
for x in range(10):
print x, "je menšie ako 10"
Pre komplexnejšie logické výrazy možno použiť príkazy continue a break:
for x in range(10):
if x == 3:
continue # Priamo prejde na ďalšiu iteráciu cyklu
if x == 5:
break # Úplne ukončí cyklus
print x
Výsledkom bude výstup 0, 1, 2 a 4.
Pravdivostné hodnoty (Truthiness)
Booleovské premenné v Pythone sa používajú podobne ako v iných jazykoch, jediný rozdiel je v tom, že ich prvé písmeno musí byť veľké:
one_is_less_than_two = 1 < 2 # je True
true_equals_false = True == False # je False
Python používa None na označenie neexistujúcej hodnoty, podobne ako null v iných jazykoch:
x = None
print x == None # Vypíše True, nie je to najelegantnejšie
print x is None # Vypíše True, je to elegantnejšie
Python vám umožňuje používať iné hodnoty namiesto booleovských hodnôt. Nasledujúce sú ekvivalentné False:
- False
- None
- [] (prázdny zoznam)
- {} (prázdny slovník)
- “”
- set()
- 0
- 0.0
Podobne existuje mnoho ekvivalentov pre True, čo vám veľmi uľahčuje kontrolu prázdnych zoznamov, reťazcov, slovníkov a podobne.
Samozrejme, ak nepredvídate výsledok, môže sa stať, že sa počas používania vyskytnú chyby:
s = some_function_that_returns_a_string()
if s:
first_char = s[0]
else:
first_char = ""
Jednoduchší prístup, ktorý má rovnaký efekt ako ten vyššie:
first_char = s and s[0]
Ak je prvá hodnota pravdivá, vráti sa druhá hodnota, inak sa vráti prvá hodnota.
Podobne, ak x môže byť číslo alebo None, takto môžete získať x, ktoré je zaručene číslom:
safe_x = x or 0
V Pythone existuje aj funkcia all, ktorá vráti True, ak sú všetky prvky pravdivé. Funkcia any vráti True, ak je aspoň jeden prvok pravdivý. Napríklad pre zoznam, kde každý prvok je „pravdivý“, funkcia all vráti True, inak vráti False:
all([True, 1, { 3 }]) # True
all([True, 1, {}]) # False, {} je ekvivalentné s „False“
any([True, 1, {}]) # True
all([]) # True, neexistuje žiadny prvok ekvivalentný s „False“
any([]) # False, neexistuje žiadny prvok ekvivalentný s „True“
Ďalšie čítanie: Bežne používaná pokročilá syntax Pythonu v dátovej vede