Python pe Scurt
Varianta rulabilă a fișierului curent poate fi accesată aici: Ziua 1 - Python
Python este un limbaj de programare simplu. Nu folosim ";" la final de instrucțiune, ci terminăm instrucțiunile la final de rând. Nu folosim "{}" pentru a secvenția bucăți de cod, ci le scriem după ":". Ce este foarte important, în schimb, este indentarea. Pentru a declara că o bucată de cod se află în interiorul unei funcții, clase, instrucțiuni etc. aceasta trebuie să fie aliniată cu un tab în plus față de header:
x = 3
print(f"Valoarea variabilei x este: {x}")
if x > 4:
print("Incorect")
else:
print("x + 1 este: ", x + 1)
Output:
Valoarea variabilei X este: 3
x + 1 este: 4
Observați afișările. Folosind funcția print putem afișa orice tip de date pus între paranteze. Nu este obligatoriu să afișăm o singură variabilă, putem afișa oricât de multe dacă punem "," între ele. Ce altceva mai puteți observa din această secvență de cod?
...
Toate variabilele în Python sunt obiecte. Asta înseamnă că le puteți atribui orice valoare fără a preciza tipul de date, și chiar să actualizați valoarea unei variabile cu un tip de date diferit fără probleme:
x = 3
y = 2.15
print(x, y)
x = "abc"
print(x)
Output:
3 2.15
abc
Același principiu se aplică și la liste (vectori). Puteți crea o listă cu variabile de tipuri diferite:
l = ['z', 1, "mac-mac", 3.14, []]
l
Output: ['z', 1, 'mac-mac', 3.14, []]
Elementele pot fi accesate direct, sau putem secționa lista raportat la start_pos:end_pos:pas (slice-uri)
Pentru următoarele exemple incercati sa vă dați seama ce o să afișeze înainte de a le apela:
print(l[1:3])
print(l[3:])
print(l[:3])
print(l[1:9:2])
print(l[-2])
print(l[:-1])
Output:
[1, 'mac-mac']
[3.14, []]
['z', 1, 'mac-mac']
[1, 3.14]
3.14
['z', 1, 'mac-mac', 3.14]
EXERCIȚIU
Folosind doar slice-uri, afișează elementele listei date în ordine inversă.
l[::-1]
Output: [[], 3.14, 'mac-mac', 1, 'z']
Majoritatea tipurilor de date comune sunt preimplementate și ușor de folosit. De exemplu, mulțimile:
my_set = set()
my_set.add(3)
print("My first set: ", my_set)
my_second_set = set([2, 6, 3, 2])
print("My second set: ", my_second_set)
print("Set union: ", my_set.union(my_second_set))
print("Set intersection: ", my_set.intersection(my_second_set))
Output:
My first set: {3}
My second set: {2, 3, 6}
Set union: {2, 3, 6}
Set intersection: {3}
Mai multe funcții cu mulțimi găsiți aici: https://docs.python.org/3/tutorial/datastructures.html#sets
Sau dicționarele:
my_dict = {
"brand": "Ford",
"model": "Mustang",
"year": 1964
}
print("My first dictionary: ", my_dict)
my_second_dict = dict(name = "John", age = 36)
print("My second dictionary: ", my_second_dict)
print()
my_second_dict["country"] = "Norway"
print("We can easily add new fields: ", my_second_dict)
my_second_dict["country"] = "Italy"
print("Or modify them: ", my_second_dict)
Output:
My first dictionary: {'brand': 'Ford', 'model': 'Mustang', 'year': 1964}
My second dictionary: {'name': 'John', 'age': 36}
We can easily add new fields: {'name': 'John', 'age': 36, 'country': 'Norway'}
Or modify them: {'name': 'John', 'age': 36, 'country': 'Italy'}
Pentru mai multe funcții pe dicționare: https://docs.python.org/3/tutorial/datastructures.html#dictionaries
Funcții & Clase
Funcțiile se definesc cu ajutorul cuvântului def. Pot avea oricât de mulți parametri, și pot returna oricât de multe valori. Parametrii pot avea valori implicite, dar restricțiile de tip sunt mai mult pentru developer -- nu vor arunca erori dacă nu sunt respectate.
def f(age: int, name = "Bran") -> str:
pass
f('Age')
Valorile implicite se află mereu la finalul listei de parametri.
Obervați cuvântul cheie pass folosit mai sus. Este o expresie vidă care poate fi utilizată în interiorul unei structuri pentru a nu arunca eroare până o completăm cu instrucțiunile dorite. O putem folosi atunci când vrem să scriem întâi headerele funcțiilor / claselor.
Clasele se definesc cu ajutorul cuvântului cheie class. Ca în orice limbaj, avem variabile statice pe care le putem apela fie la nivel de clasă, fie la nivel de instanță a clasei:
class Clasa:
x = 10
Clasa.x
Output: 10
instanta = Clasa()
instanta.x
Output: 10
Cu ce seamănă clasele din ce ați mai făcut până acum?
...
Funcțiile din clase încep mereu cu operatorul self -- referință către clasa respectivă. Referința poate avea orice denumire, self este doar o convenție.
class Clasa:
x = 3
def f(self, x):
return self.x, x
instanta = Clasa()
instanta.f(7)
Output: (3, 7)
Observă cum x și self.x sunt variabile complet separate. În Python, parametrii funcțiilor mereu sunt considerați independenți de mediul exterior, în timp ce elementele care încep cu self. sunt specifici instanței clasei respective.
Pe lângă funcțiile normale avem și o serie de funcții implicite:
- __init__ -> inițializarea clasei (constructor)
- __str__ -> transformarea clasei în instanță string
- __lt__ -> definiția operatorului <
- __le__ -> definiția operatorului <=
- __gt__ -> definiția operatorului >
Funcțiile pot fi apelate cu denumirea lor, dar și direct, folosind simbolul respectiv.
class Clasa:
def __init__(self, x):
self.x = x
def __str__(self):
return "Valoarea clasei: " + str(self.x)
instanta = Clasa(5)
print(instanta)
Output: Valoarea clasei: 5
EXERCIȚIU
Creează o clasă cu minim 2 elemente. Creează 2 instanțe pentru noua clasă și afișeaz-o pe cea mai mare în urma comparației dintre ele.
class Clasa:
def __init__(self, x, y):
self.x = x
self.y = y
def __lt__(self, cls):
return self.y < cls.y if self.x == cls.x else self.x < cls.x
def __str__(self):
return f"x: {self.x}\ny: {self.y}"
instanta1 = Clasa(3, 9)
instanta2 = Clasa(5, 6)
print(max(instanta1, instanta2))
Output:
x: 5
y: 6
Vom descoperi mai multe despre limbaj pe măsură ce lucrăm cu el.
Puteți găsi mai multe exemple aici: https://colab.research.google.com/drive/1Lxed6J79CsWwyrr8vpLugTmS6GMwMA-j?usp=drive_link
Sau în documentația limbajului: https://docs.python.org/3/
Regex
Un RegEx reprezintă o Expresie Regulată (codificarea unei secvențe de caractere). Poate fi folosit pentru a identifica secvențe de caractere într-un șir, pentru a înlocui secvențe sau pentru a separa un șir în funcție de diferite metrici. O secvență de căutare arată așa:
import re
txt = "The rain in Spain stays mainly in the plain"
x = re.search("Spain", txt)
if x:
print("Cuvântul există în șir")
else:
print("Cuvântul nu există în șir")
Output: Cuvântul există în șir
Există o serie de reguli și simboluri pe care le putem folosi pentru a descrie secvența de caractere căutată. O să modificăm exemplul original pentru a ne uita la câteva exemple.
Putem pune [.] în pozițiile în care poate fi orice caracter, [^] este caracterul început de șir și [$] este caracterul pentru final de șir.
print(re.findall("Sp.in", txt))
print(re.findall("^The rain in Spain stays mainly in the plain$", txt))
Output:
['Spain']
['The rain in Spain stays mainly in the plain']
Dacă punem [+] după un caracter acela trebuie să apară minim o dată. Dacă punem [*] după un caracter, acela poate să apară de oricâte ori, chiar și 0. Simbolurile pot fi combinate: [.+] înseamnă că putem avea o listă de caractere oricât de lungă.
x = re.findall(".*ai", txt)
print(x)
Output: ['The rain in Spain stays mainly in the plai']
În loc de a folosi [.+] putem folosi secvențe specifice:
- \d identifică o listă de cifre
- \D - caractere care nu sunt cifre
- \s - caracterul spațiu
- \w - litere mici și mari, cifre și caracterul "_"
Pentru a fi și mai specifici putem folosi seturi:
- [ar] - cel puțin unul din caracterele "a" și "r" este prezent
- [a-n] - orice caracter lowercase din intervalul dat
- [0-9] - putem aplica intervalele și pentru cifre
- [a-zA-Z] - sau le putem concatena pentru a accepta caractere mai variate
- [1-3][7-9] - două seturi unul în continuarea celuilalt funcționează ca orice alte simboluri legate. Exemplul dat caută o secvență de 2 cifre, unde prima cifră este în intervalul 1-3, iar a doua în intervalul 7-9
Putem folosi secvențele de mai sus pentru a identifica toate cuvintele care conțin șirul "ai", de exemplu:
x = re.findall("\w*ai\w", txt)
print(x)
Output: ['rain', 'Spain', 'main', 'plain']
Lista completă de reguli și simboluri se află aici: https://docs.python.org/3/library/re.html
EXERCIȚIU
Creează o funcție de preprocesare a textului: funcția va primi un șir de caractere, îl va împărți în cuvinte și va elimina toate caracterele care nu sunt litere. Modifică funcția astfel încât să păstreze cratimele din cuvinte.
txt = "M-am dus la piata - asta voiam? Vom ajunge repede, cred, acasa!"
Lucru cu fișiere
O să ne conectăm întâi la contul de drive ca să accesăm mai ușor fișierele:
from google.colab import drive
drive.mount('/content/drive/')
Output: Mounted at /content/drive/
Stabilim locația "terminalului" în folderul acestui curs:
import os
os.chdir("/content/drive/MyDrive/Cram School")
Ați mai lucrat cu un terminal înainte? Putem apela anumite comenzi de linux dacă punem "!" în față. De exemplu, putem lista toate fișierele din folderul în care ne aflăm:
!ls
Output:
'Curs 1 - Python.ipynb'
'Curs 2 - Supervised Models.ipynb'
'Curs 3 - Preprocessing & Embeddings.ipynb'
'Curs 4 - Unsupervised Models & Ensembles.ipynb'
'Curs 5 - Scaling, Metrici & NLP.ipynb'
EXERCIȚIU
Identifică alte comenzi pe care le poți apela din terminalul colab, fie cu "!" fie cu ajutorul librăriei os:
Pentru a deschide un fișier folosim metoda open(cale_fisier, mod_deschidere).
f = open("input.txt", "r")
Există 4 tipuri de fișiere (mod_deschidere):
- "r" - citește dintr-un fișier care deja există
- "w" - scrie într-un fișier, creează fișierul dacă nu există deja
- "a" - adaugă la informația deja scrisă dintr-un fișier, îl creează dacă nu există deja
- "x" - creează un fișier, returnează eroare dacă deja există
Există mai multe metode de a citi sau scrie într-un fișier:
- read() - citește fișierul complet
- readlines() - citește pe rând câte o linie din fișier
- write() - scrie în fișier
sir = f.read()
print(sir)
Nu uitați să închideți fișierele deschise!
f.close()
EXERCIȚIU
Creează un fișier cu extensia .csv sau .xls și adaugă în el 3 linii de text. Închide fișierul, deschide-l din nou, citește și afișează informația. Poți folosi orice metode vrei: